diff options
Diffstat (limited to 'fs')
203 files changed, 4427 insertions, 2661 deletions
diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c index 873802de21cd..fbb12dadba83 100644 --- a/fs/9p/v9fs.c +++ b/fs/9p/v9fs.c | |||
@@ -82,7 +82,7 @@ static match_table_t tokens = { | |||
82 | 82 | ||
83 | static void v9fs_parse_options(struct v9fs_session_info *v9ses) | 83 | static void v9fs_parse_options(struct v9fs_session_info *v9ses) |
84 | { | 84 | { |
85 | char *options = v9ses->options; | 85 | char *options; |
86 | substring_t args[MAX_OPT_ARGS]; | 86 | substring_t args[MAX_OPT_ARGS]; |
87 | char *p; | 87 | char *p; |
88 | int option; | 88 | int option; |
@@ -96,9 +96,10 @@ static void v9fs_parse_options(struct v9fs_session_info *v9ses) | |||
96 | v9ses->cache = 0; | 96 | v9ses->cache = 0; |
97 | v9ses->trans = v9fs_default_trans(); | 97 | v9ses->trans = v9fs_default_trans(); |
98 | 98 | ||
99 | if (!options) | 99 | if (!v9ses->options) |
100 | return; | 100 | return; |
101 | 101 | ||
102 | options = kstrdup(v9ses->options, GFP_KERNEL); | ||
102 | while ((p = strsep(&options, ",")) != NULL) { | 103 | while ((p = strsep(&options, ",")) != NULL) { |
103 | int token; | 104 | int token; |
104 | if (!*p) | 105 | if (!*p) |
@@ -162,12 +163,14 @@ static void v9fs_parse_options(struct v9fs_session_info *v9ses) | |||
162 | if (*e != '\0') | 163 | if (*e != '\0') |
163 | v9ses->uid = ~0; | 164 | v9ses->uid = ~0; |
164 | } | 165 | } |
166 | kfree(s); | ||
165 | break; | 167 | break; |
166 | 168 | ||
167 | default: | 169 | default: |
168 | continue; | 170 | continue; |
169 | } | 171 | } |
170 | } | 172 | } |
173 | kfree(options); | ||
171 | } | 174 | } |
172 | 175 | ||
173 | /** | 176 | /** |
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index 175b4d9bf3f8..23581bcb599b 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c | |||
@@ -687,10 +687,10 @@ v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
687 | retval = p9_client_wstat(oldfid, &wstat); | 687 | retval = p9_client_wstat(oldfid, &wstat); |
688 | 688 | ||
689 | clunk_newdir: | 689 | clunk_newdir: |
690 | p9_client_clunk(olddirfid); | 690 | p9_client_clunk(newdirfid); |
691 | 691 | ||
692 | clunk_olddir: | 692 | clunk_olddir: |
693 | p9_client_clunk(newdirfid); | 693 | p9_client_clunk(olddirfid); |
694 | 694 | ||
695 | done: | 695 | done: |
696 | return retval; | 696 | return retval; |
diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c index bb0cef9a6b8a..678c02f1ae23 100644 --- a/fs/9p/vfs_super.c +++ b/fs/9p/vfs_super.c | |||
@@ -119,6 +119,7 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags, | |||
119 | 119 | ||
120 | P9_DPRINTK(P9_DEBUG_VFS, " \n"); | 120 | P9_DPRINTK(P9_DEBUG_VFS, " \n"); |
121 | 121 | ||
122 | st = NULL; | ||
122 | v9ses = kzalloc(sizeof(struct v9fs_session_info), GFP_KERNEL); | 123 | v9ses = kzalloc(sizeof(struct v9fs_session_info), GFP_KERNEL); |
123 | if (!v9ses) | 124 | if (!v9ses) |
124 | return -ENOMEM; | 125 | return -ENOMEM; |
@@ -164,10 +165,12 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags, | |||
164 | root->d_inode->i_ino = v9fs_qid2ino(&st->qid); | 165 | root->d_inode->i_ino = v9fs_qid2ino(&st->qid); |
165 | v9fs_stat2inode(st, root->d_inode, sb); | 166 | v9fs_stat2inode(st, root->d_inode, sb); |
166 | v9fs_fid_add(root, fid); | 167 | v9fs_fid_add(root, fid); |
168 | kfree(st); | ||
167 | 169 | ||
168 | return simple_set_mnt(mnt, sb); | 170 | return simple_set_mnt(mnt, sb); |
169 | 171 | ||
170 | error: | 172 | error: |
173 | kfree(st); | ||
171 | if (fid) | 174 | if (fid) |
172 | p9_client_clunk(fid); | 175 | p9_client_clunk(fid); |
173 | 176 | ||
diff --git a/fs/Kconfig b/fs/Kconfig index e31f3691b151..635f3e286ad8 100644 --- a/fs/Kconfig +++ b/fs/Kconfig | |||
@@ -220,7 +220,7 @@ config JBD | |||
220 | 220 | ||
221 | config JBD_DEBUG | 221 | config JBD_DEBUG |
222 | bool "JBD (ext3) debugging support" | 222 | bool "JBD (ext3) debugging support" |
223 | depends on JBD | 223 | depends on JBD && DEBUG_FS |
224 | help | 224 | help |
225 | If you are using the ext3 journaled file system (or potentially any | 225 | If you are using the ext3 journaled file system (or potentially any |
226 | other file system/device using JBD), this option allows you to | 226 | other file system/device using JBD), this option allows you to |
@@ -229,10 +229,10 @@ config JBD_DEBUG | |||
229 | debugging output will be turned off. | 229 | debugging output will be turned off. |
230 | 230 | ||
231 | If you select Y here, then you will be able to turn on debugging | 231 | If you select Y here, then you will be able to turn on debugging |
232 | with "echo N > /proc/sys/fs/jbd-debug", where N is a number between | 232 | with "echo N > /sys/kernel/debug/jbd/jbd-debug", where N is a |
233 | 1 and 5, the higher the number, the more debugging output is | 233 | number between 1 and 5, the higher the number, the more debugging |
234 | generated. To turn debugging off again, do | 234 | output is generated. To turn debugging off again, do |
235 | "echo 0 > /proc/sys/fs/jbd-debug". | 235 | "echo 0 > /sys/kernel/debug/jbd/jbd-debug". |
236 | 236 | ||
237 | config JBD2 | 237 | config JBD2 |
238 | tristate | 238 | tristate |
@@ -459,6 +459,15 @@ config OCFS2_DEBUG_MASKLOG | |||
459 | This option will enlarge your kernel, but it allows debugging of | 459 | This option will enlarge your kernel, but it allows debugging of |
460 | ocfs2 filesystem issues. | 460 | ocfs2 filesystem issues. |
461 | 461 | ||
462 | config OCFS2_DEBUG_FS | ||
463 | bool "OCFS2 expensive checks" | ||
464 | depends on OCFS2_FS | ||
465 | default n | ||
466 | help | ||
467 | This option will enable expensive consistency checks. Enable | ||
468 | this option for debugging only as it is likely to decrease | ||
469 | performance of the filesystem. | ||
470 | |||
462 | config MINIX_FS | 471 | config MINIX_FS |
463 | tristate "Minix fs support" | 472 | tristate "Minix fs support" |
464 | help | 473 | help |
@@ -504,7 +513,7 @@ config INOTIFY | |||
504 | including multiple file events, one-shot support, and unmount | 513 | including multiple file events, one-shot support, and unmount |
505 | notification. | 514 | notification. |
506 | 515 | ||
507 | For more information, see Documentation/filesystems/inotify.txt | 516 | For more information, see <file:Documentation/filesystems/inotify.txt> |
508 | 517 | ||
509 | If unsure, say Y. | 518 | If unsure, say Y. |
510 | 519 | ||
@@ -518,7 +527,7 @@ config INOTIFY_USER | |||
518 | directories via a single open fd. Events are read from the file | 527 | directories via a single open fd. Events are read from the file |
519 | descriptor, which is also select()- and poll()-able. | 528 | descriptor, which is also select()- and poll()-able. |
520 | 529 | ||
521 | For more information, see Documentation/filesystems/inotify.txt | 530 | For more information, see <file:Documentation/filesystems/inotify.txt> |
522 | 531 | ||
523 | If unsure, say Y. | 532 | If unsure, say Y. |
524 | 533 | ||
@@ -1089,7 +1098,7 @@ config ECRYPT_FS | |||
1089 | depends on EXPERIMENTAL && KEYS && CRYPTO && NET | 1098 | depends on EXPERIMENTAL && KEYS && CRYPTO && NET |
1090 | help | 1099 | help |
1091 | Encrypted filesystem that operates on the VFS layer. See | 1100 | Encrypted filesystem that operates on the VFS layer. See |
1092 | <file:Documentation/ecryptfs.txt> to learn more about | 1101 | <file:Documentation/filesystems/ecryptfs.txt> to learn more about |
1093 | eCryptfs. Userspace components are required and can be | 1102 | eCryptfs. Userspace components are required and can be |
1094 | obtained from <http://ecryptfs.sf.net>. | 1103 | obtained from <http://ecryptfs.sf.net>. |
1095 | 1104 | ||
@@ -2007,7 +2016,7 @@ config CIFS_EXPERIMENTAL | |||
2007 | config CIFS_UPCALL | 2016 | config CIFS_UPCALL |
2008 | bool "Kerberos/SPNEGO advanced session setup (EXPERIMENTAL)" | 2017 | bool "Kerberos/SPNEGO advanced session setup (EXPERIMENTAL)" |
2009 | depends on CIFS_EXPERIMENTAL | 2018 | depends on CIFS_EXPERIMENTAL |
2010 | depends on CONNECTOR | 2019 | depends on KEYS |
2011 | help | 2020 | help |
2012 | Enables an upcall mechanism for CIFS which will be used to contact | 2021 | Enables an upcall mechanism for CIFS which will be used to contact |
2013 | userspace helper utilities to provide SPNEGO packaged Kerberos | 2022 | userspace helper utilities to provide SPNEGO packaged Kerberos |
diff --git a/fs/afs/vlocation.c b/fs/afs/vlocation.c index 7b4bbe48112d..849fc3160cb5 100644 --- a/fs/afs/vlocation.c +++ b/fs/afs/vlocation.c | |||
@@ -382,7 +382,7 @@ struct afs_vlocation *afs_vlocation_lookup(struct afs_cell *cell, | |||
382 | cell->name, key_serial(key), | 382 | cell->name, key_serial(key), |
383 | (int) namesz, (int) namesz, name, namesz); | 383 | (int) namesz, (int) namesz, name, namesz); |
384 | 384 | ||
385 | if (namesz > sizeof(vl->vldb.name)) { | 385 | if (namesz >= sizeof(vl->vldb.name)) { |
386 | _leave(" = -ENAMETOOLONG"); | 386 | _leave(" = -ENAMETOOLONG"); |
387 | return ERR_PTR(-ENAMETOOLONG); | 387 | return ERR_PTR(-ENAMETOOLONG); |
388 | } | 388 | } |
@@ -1161,7 +1161,12 @@ retry: | |||
1161 | ret = 0; | 1161 | ret = 0; |
1162 | if (to.timed_out) /* Only check after read evt */ | 1162 | if (to.timed_out) /* Only check after read evt */ |
1163 | break; | 1163 | break; |
1164 | io_schedule(); | 1164 | /* Try to only show up in io wait if there are ops |
1165 | * in flight */ | ||
1166 | if (ctx->reqs_active) | ||
1167 | io_schedule(); | ||
1168 | else | ||
1169 | schedule(); | ||
1165 | if (signal_pending(tsk)) { | 1170 | if (signal_pending(tsk)) { |
1166 | ret = -EINTR; | 1171 | ret = -EINTR; |
1167 | break; | 1172 | break; |
diff --git a/fs/autofs/inode.c b/fs/autofs/inode.c index e7204d71acc9..45f5992a0957 100644 --- a/fs/autofs/inode.c +++ b/fs/autofs/inode.c | |||
@@ -80,7 +80,7 @@ static int parse_options(char *options, int *pipefd, uid_t *uid, gid_t *gid, | |||
80 | 80 | ||
81 | *uid = current->uid; | 81 | *uid = current->uid; |
82 | *gid = current->gid; | 82 | *gid = current->gid; |
83 | *pgrp = process_group(current); | 83 | *pgrp = task_pgrp_nr(current); |
84 | 84 | ||
85 | *minproto = *maxproto = AUTOFS_PROTO_VERSION; | 85 | *minproto = *maxproto = AUTOFS_PROTO_VERSION; |
86 | 86 | ||
diff --git a/fs/autofs/root.c b/fs/autofs/root.c index c1489533277a..5efff3c0d886 100644 --- a/fs/autofs/root.c +++ b/fs/autofs/root.c | |||
@@ -214,8 +214,8 @@ static struct dentry *autofs_root_lookup(struct inode *dir, struct dentry *dentr | |||
214 | 214 | ||
215 | oz_mode = autofs_oz_mode(sbi); | 215 | oz_mode = autofs_oz_mode(sbi); |
216 | DPRINTK(("autofs_lookup: pid = %u, pgrp = %u, catatonic = %d, " | 216 | DPRINTK(("autofs_lookup: pid = %u, pgrp = %u, catatonic = %d, " |
217 | "oz_mode = %d\n", pid_nr(task_pid(current)), | 217 | "oz_mode = %d\n", task_pid_nr(current), |
218 | process_group(current), sbi->catatonic, | 218 | task_pgrp_nr(current), sbi->catatonic, |
219 | oz_mode)); | 219 | oz_mode)); |
220 | 220 | ||
221 | /* | 221 | /* |
@@ -536,7 +536,7 @@ static int autofs_root_ioctl(struct inode *inode, struct file *filp, | |||
536 | struct autofs_sb_info *sbi = autofs_sbi(inode->i_sb); | 536 | struct autofs_sb_info *sbi = autofs_sbi(inode->i_sb); |
537 | void __user *argp = (void __user *)arg; | 537 | void __user *argp = (void __user *)arg; |
538 | 538 | ||
539 | DPRINTK(("autofs_ioctl: cmd = 0x%08x, arg = 0x%08lx, sbi = %p, pgrp = %u\n",cmd,arg,sbi,process_group(current))); | 539 | DPRINTK(("autofs_ioctl: cmd = 0x%08x, arg = 0x%08lx, sbi = %p, pgrp = %u\n",cmd,arg,sbi,task_pgrp_nr(current))); |
540 | 540 | ||
541 | if (_IOC_TYPE(cmd) != _IOC_TYPE(AUTOFS_IOC_FIRST) || | 541 | if (_IOC_TYPE(cmd) != _IOC_TYPE(AUTOFS_IOC_FIRST) || |
542 | _IOC_NR(cmd) - _IOC_NR(AUTOFS_IOC_FIRST) >= AUTOFS_IOC_COUNT) | 542 | _IOC_NR(cmd) - _IOC_NR(AUTOFS_IOC_FIRST) >= AUTOFS_IOC_COUNT) |
diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h index d85f42fa9206..2d4ae40718d9 100644 --- a/fs/autofs4/autofs_i.h +++ b/fs/autofs4/autofs_i.h | |||
@@ -131,7 +131,7 @@ static inline struct autofs_info *autofs4_dentry_ino(struct dentry *dentry) | |||
131 | filesystem without "magic".) */ | 131 | filesystem without "magic".) */ |
132 | 132 | ||
133 | static inline int autofs4_oz_mode(struct autofs_sb_info *sbi) { | 133 | static inline int autofs4_oz_mode(struct autofs_sb_info *sbi) { |
134 | return sbi->catatonic || process_group(current) == sbi->oz_pgrp; | 134 | return sbi->catatonic || task_pgrp_nr(current) == sbi->oz_pgrp; |
135 | } | 135 | } |
136 | 136 | ||
137 | /* Does a dentry have some pending activity? */ | 137 | /* Does a dentry have some pending activity? */ |
diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c index cd81f0836671..7f05d6ccdb13 100644 --- a/fs/autofs4/inode.c +++ b/fs/autofs4/inode.c | |||
@@ -226,7 +226,7 @@ static int parse_options(char *options, int *pipefd, uid_t *uid, gid_t *gid, | |||
226 | 226 | ||
227 | *uid = current->uid; | 227 | *uid = current->uid; |
228 | *gid = current->gid; | 228 | *gid = current->gid; |
229 | *pgrp = process_group(current); | 229 | *pgrp = task_pgrp_nr(current); |
230 | 230 | ||
231 | *minproto = AUTOFS_MIN_PROTO_VERSION; | 231 | *minproto = AUTOFS_MIN_PROTO_VERSION; |
232 | *maxproto = AUTOFS_MAX_PROTO_VERSION; | 232 | *maxproto = AUTOFS_MAX_PROTO_VERSION; |
@@ -323,7 +323,7 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent) | |||
323 | sbi->pipe = NULL; | 323 | sbi->pipe = NULL; |
324 | sbi->catatonic = 1; | 324 | sbi->catatonic = 1; |
325 | sbi->exp_timeout = 0; | 325 | sbi->exp_timeout = 0; |
326 | sbi->oz_pgrp = process_group(current); | 326 | sbi->oz_pgrp = task_pgrp_nr(current); |
327 | sbi->sb = s; | 327 | sbi->sb = s; |
328 | sbi->version = 0; | 328 | sbi->version = 0; |
329 | sbi->sub_version = 0; | 329 | sbi->sub_version = 0; |
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c index 45ff3d63b758..2bbcc8151dc3 100644 --- a/fs/autofs4/root.c +++ b/fs/autofs4/root.c | |||
@@ -582,7 +582,7 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s | |||
582 | oz_mode = autofs4_oz_mode(sbi); | 582 | oz_mode = autofs4_oz_mode(sbi); |
583 | 583 | ||
584 | DPRINTK("pid = %u, pgrp = %u, catatonic = %d, oz_mode = %d", | 584 | DPRINTK("pid = %u, pgrp = %u, catatonic = %d, oz_mode = %d", |
585 | current->pid, process_group(current), sbi->catatonic, oz_mode); | 585 | current->pid, task_pgrp_nr(current), sbi->catatonic, oz_mode); |
586 | 586 | ||
587 | unhashed = autofs4_lookup_unhashed(sbi, dentry->d_parent, &dentry->d_name); | 587 | unhashed = autofs4_lookup_unhashed(sbi, dentry->d_parent, &dentry->d_name); |
588 | if (!unhashed) { | 588 | if (!unhashed) { |
@@ -976,7 +976,7 @@ static int autofs4_root_ioctl(struct inode *inode, struct file *filp, | |||
976 | void __user *p = (void __user *)arg; | 976 | void __user *p = (void __user *)arg; |
977 | 977 | ||
978 | DPRINTK("cmd = 0x%08x, arg = 0x%08lx, sbi = %p, pgrp = %u", | 978 | DPRINTK("cmd = 0x%08x, arg = 0x%08lx, sbi = %p, pgrp = %u", |
979 | cmd,arg,sbi,process_group(current)); | 979 | cmd,arg,sbi,task_pgrp_nr(current)); |
980 | 980 | ||
981 | if (_IOC_TYPE(cmd) != _IOC_TYPE(AUTOFS_IOC_FIRST) || | 981 | if (_IOC_TYPE(cmd) != _IOC_TYPE(AUTOFS_IOC_FIRST) || |
982 | _IOC_NR(cmd) - _IOC_NR(AUTOFS_IOC_FIRST) >= AUTOFS_IOC_COUNT) | 982 | _IOC_NR(cmd) - _IOC_NR(AUTOFS_IOC_FIRST) >= AUTOFS_IOC_COUNT) |
diff --git a/fs/bfs/bfs.h b/fs/bfs/bfs.h index 130f6c66c5ba..ac7a8b1d6c3a 100644 --- a/fs/bfs/bfs.h +++ b/fs/bfs/bfs.h | |||
@@ -14,8 +14,6 @@ struct bfs_sb_info { | |||
14 | unsigned long si_blocks; | 14 | unsigned long si_blocks; |
15 | unsigned long si_freeb; | 15 | unsigned long si_freeb; |
16 | unsigned long si_freei; | 16 | unsigned long si_freei; |
17 | unsigned long si_lf_ioff; | ||
18 | unsigned long si_lf_sblk; | ||
19 | unsigned long si_lf_eblk; | 17 | unsigned long si_lf_eblk; |
20 | unsigned long si_lasti; | 18 | unsigned long si_lasti; |
21 | unsigned long * si_imap; | 19 | unsigned long * si_imap; |
@@ -39,7 +37,7 @@ static inline struct bfs_sb_info *BFS_SB(struct super_block *sb) | |||
39 | 37 | ||
40 | static inline struct bfs_inode_info *BFS_I(struct inode *inode) | 38 | static inline struct bfs_inode_info *BFS_I(struct inode *inode) |
41 | { | 39 | { |
42 | return list_entry(inode, struct bfs_inode_info, vfs_inode); | 40 | return container_of(inode, struct bfs_inode_info, vfs_inode); |
43 | } | 41 | } |
44 | 42 | ||
45 | 43 | ||
diff --git a/fs/bfs/dir.c b/fs/bfs/dir.c index 097f1497f743..1fd056d0fc3d 100644 --- a/fs/bfs/dir.c +++ b/fs/bfs/dir.c | |||
@@ -21,29 +21,32 @@ | |||
21 | #define dprintf(x...) | 21 | #define dprintf(x...) |
22 | #endif | 22 | #endif |
23 | 23 | ||
24 | static int bfs_add_entry(struct inode * dir, const unsigned char * name, int namelen, int ino); | 24 | static int bfs_add_entry(struct inode *dir, const unsigned char *name, |
25 | static struct buffer_head * bfs_find_entry(struct inode * dir, | 25 | int namelen, int ino); |
26 | const unsigned char * name, int namelen, struct bfs_dirent ** res_dir); | 26 | static struct buffer_head *bfs_find_entry(struct inode *dir, |
27 | const unsigned char *name, int namelen, | ||
28 | struct bfs_dirent **res_dir); | ||
27 | 29 | ||
28 | static int bfs_readdir(struct file * f, void * dirent, filldir_t filldir) | 30 | static int bfs_readdir(struct file *f, void *dirent, filldir_t filldir) |
29 | { | 31 | { |
30 | struct inode * dir = f->f_path.dentry->d_inode; | 32 | struct inode *dir = f->f_path.dentry->d_inode; |
31 | struct buffer_head * bh; | 33 | struct buffer_head *bh; |
32 | struct bfs_dirent * de; | 34 | struct bfs_dirent *de; |
33 | unsigned int offset; | 35 | unsigned int offset; |
34 | int block; | 36 | int block; |
35 | 37 | ||
36 | lock_kernel(); | 38 | lock_kernel(); |
37 | 39 | ||
38 | if (f->f_pos & (BFS_DIRENT_SIZE-1)) { | 40 | if (f->f_pos & (BFS_DIRENT_SIZE - 1)) { |
39 | printf("Bad f_pos=%08lx for %s:%08lx\n", (unsigned long)f->f_pos, | 41 | printf("Bad f_pos=%08lx for %s:%08lx\n", |
40 | dir->i_sb->s_id, dir->i_ino); | 42 | (unsigned long)f->f_pos, |
43 | dir->i_sb->s_id, dir->i_ino); | ||
41 | unlock_kernel(); | 44 | unlock_kernel(); |
42 | return -EBADF; | 45 | return -EBADF; |
43 | } | 46 | } |
44 | 47 | ||
45 | while (f->f_pos < dir->i_size) { | 48 | while (f->f_pos < dir->i_size) { |
46 | offset = f->f_pos & (BFS_BSIZE-1); | 49 | offset = f->f_pos & (BFS_BSIZE - 1); |
47 | block = BFS_I(dir)->i_sblock + (f->f_pos >> BFS_BSIZE_BITS); | 50 | block = BFS_I(dir)->i_sblock + (f->f_pos >> BFS_BSIZE_BITS); |
48 | bh = sb_bread(dir->i_sb, block); | 51 | bh = sb_bread(dir->i_sb, block); |
49 | if (!bh) { | 52 | if (!bh) { |
@@ -54,7 +57,9 @@ static int bfs_readdir(struct file * f, void * dirent, filldir_t filldir) | |||
54 | de = (struct bfs_dirent *)(bh->b_data + offset); | 57 | de = (struct bfs_dirent *)(bh->b_data + offset); |
55 | if (de->ino) { | 58 | if (de->ino) { |
56 | int size = strnlen(de->name, BFS_NAMELEN); | 59 | int size = strnlen(de->name, BFS_NAMELEN); |
57 | if (filldir(dirent, de->name, size, f->f_pos, le16_to_cpu(de->ino), DT_UNKNOWN) < 0) { | 60 | if (filldir(dirent, de->name, size, f->f_pos, |
61 | le16_to_cpu(de->ino), | ||
62 | DT_UNKNOWN) < 0) { | ||
58 | brelse(bh); | 63 | brelse(bh); |
59 | unlock_kernel(); | 64 | unlock_kernel(); |
60 | return 0; | 65 | return 0; |
@@ -62,7 +67,7 @@ static int bfs_readdir(struct file * f, void * dirent, filldir_t filldir) | |||
62 | } | 67 | } |
63 | offset += BFS_DIRENT_SIZE; | 68 | offset += BFS_DIRENT_SIZE; |
64 | f->f_pos += BFS_DIRENT_SIZE; | 69 | f->f_pos += BFS_DIRENT_SIZE; |
65 | } while (offset < BFS_BSIZE && f->f_pos < dir->i_size); | 70 | } while ((offset < BFS_BSIZE) && (f->f_pos < dir->i_size)); |
66 | brelse(bh); | 71 | brelse(bh); |
67 | } | 72 | } |
68 | 73 | ||
@@ -78,13 +83,13 @@ const struct file_operations bfs_dir_operations = { | |||
78 | 83 | ||
79 | extern void dump_imap(const char *, struct super_block *); | 84 | extern void dump_imap(const char *, struct super_block *); |
80 | 85 | ||
81 | static int bfs_create(struct inode * dir, struct dentry * dentry, int mode, | 86 | static int bfs_create(struct inode *dir, struct dentry *dentry, int mode, |
82 | struct nameidata *nd) | 87 | struct nameidata *nd) |
83 | { | 88 | { |
84 | int err; | 89 | int err; |
85 | struct inode * inode; | 90 | struct inode *inode; |
86 | struct super_block * s = dir->i_sb; | 91 | struct super_block *s = dir->i_sb; |
87 | struct bfs_sb_info * info = BFS_SB(s); | 92 | struct bfs_sb_info *info = BFS_SB(s); |
88 | unsigned long ino; | 93 | unsigned long ino; |
89 | 94 | ||
90 | inode = new_inode(s); | 95 | inode = new_inode(s); |
@@ -97,7 +102,7 @@ static int bfs_create(struct inode * dir, struct dentry * dentry, int mode, | |||
97 | iput(inode); | 102 | iput(inode); |
98 | return -ENOSPC; | 103 | return -ENOSPC; |
99 | } | 104 | } |
100 | set_bit(ino, info->si_imap); | 105 | set_bit(ino, info->si_imap); |
101 | info->si_freei--; | 106 | info->si_freei--; |
102 | inode->i_uid = current->fsuid; | 107 | inode->i_uid = current->fsuid; |
103 | inode->i_gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid; | 108 | inode->i_gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid; |
@@ -113,9 +118,10 @@ static int bfs_create(struct inode * dir, struct dentry * dentry, int mode, | |||
113 | BFS_I(inode)->i_eblock = 0; | 118 | BFS_I(inode)->i_eblock = 0; |
114 | insert_inode_hash(inode); | 119 | insert_inode_hash(inode); |
115 | mark_inode_dirty(inode); | 120 | mark_inode_dirty(inode); |
116 | dump_imap("create",s); | 121 | dump_imap("create", s); |
117 | 122 | ||
118 | err = bfs_add_entry(dir, dentry->d_name.name, dentry->d_name.len, inode->i_ino); | 123 | err = bfs_add_entry(dir, dentry->d_name.name, dentry->d_name.len, |
124 | inode->i_ino); | ||
119 | if (err) { | 125 | if (err) { |
120 | inode_dec_link_count(inode); | 126 | inode_dec_link_count(inode); |
121 | iput(inode); | 127 | iput(inode); |
@@ -127,11 +133,12 @@ static int bfs_create(struct inode * dir, struct dentry * dentry, int mode, | |||
127 | return 0; | 133 | return 0; |
128 | } | 134 | } |
129 | 135 | ||
130 | static struct dentry * bfs_lookup(struct inode * dir, struct dentry * dentry, struct nameidata *nd) | 136 | static struct dentry *bfs_lookup(struct inode *dir, struct dentry *dentry, |
137 | struct nameidata *nd) | ||
131 | { | 138 | { |
132 | struct inode * inode = NULL; | 139 | struct inode *inode = NULL; |
133 | struct buffer_head * bh; | 140 | struct buffer_head *bh; |
134 | struct bfs_dirent * de; | 141 | struct bfs_dirent *de; |
135 | 142 | ||
136 | if (dentry->d_name.len > BFS_NAMELEN) | 143 | if (dentry->d_name.len > BFS_NAMELEN) |
137 | return ERR_PTR(-ENAMETOOLONG); | 144 | return ERR_PTR(-ENAMETOOLONG); |
@@ -152,13 +159,15 @@ static struct dentry * bfs_lookup(struct inode * dir, struct dentry * dentry, st | |||
152 | return NULL; | 159 | return NULL; |
153 | } | 160 | } |
154 | 161 | ||
155 | static int bfs_link(struct dentry * old, struct inode * dir, struct dentry * new) | 162 | static int bfs_link(struct dentry *old, struct inode *dir, |
163 | struct dentry *new) | ||
156 | { | 164 | { |
157 | struct inode * inode = old->d_inode; | 165 | struct inode *inode = old->d_inode; |
158 | int err; | 166 | int err; |
159 | 167 | ||
160 | lock_kernel(); | 168 | lock_kernel(); |
161 | err = bfs_add_entry(dir, new->d_name.name, new->d_name.len, inode->i_ino); | 169 | err = bfs_add_entry(dir, new->d_name.name, new->d_name.len, |
170 | inode->i_ino); | ||
162 | if (err) { | 171 | if (err) { |
163 | unlock_kernel(); | 172 | unlock_kernel(); |
164 | return err; | 173 | return err; |
@@ -172,23 +181,23 @@ static int bfs_link(struct dentry * old, struct inode * dir, struct dentry * new | |||
172 | return 0; | 181 | return 0; |
173 | } | 182 | } |
174 | 183 | ||
175 | 184 | static int bfs_unlink(struct inode *dir, struct dentry *dentry) | |
176 | static int bfs_unlink(struct inode * dir, struct dentry * dentry) | ||
177 | { | 185 | { |
178 | int error = -ENOENT; | 186 | int error = -ENOENT; |
179 | struct inode * inode; | 187 | struct inode *inode; |
180 | struct buffer_head * bh; | 188 | struct buffer_head *bh; |
181 | struct bfs_dirent * de; | 189 | struct bfs_dirent *de; |
182 | 190 | ||
183 | inode = dentry->d_inode; | 191 | inode = dentry->d_inode; |
184 | lock_kernel(); | 192 | lock_kernel(); |
185 | bh = bfs_find_entry(dir, dentry->d_name.name, dentry->d_name.len, &de); | 193 | bh = bfs_find_entry(dir, dentry->d_name.name, dentry->d_name.len, &de); |
186 | if (!bh || le16_to_cpu(de->ino) != inode->i_ino) | 194 | if (!bh || (le16_to_cpu(de->ino) != inode->i_ino)) |
187 | goto out_brelse; | 195 | goto out_brelse; |
188 | 196 | ||
189 | if (!inode->i_nlink) { | 197 | if (!inode->i_nlink) { |
190 | printf("unlinking non-existent file %s:%lu (nlink=%d)\n", inode->i_sb->s_id, | 198 | printf("unlinking non-existent file %s:%lu (nlink=%d)\n", |
191 | inode->i_ino, inode->i_nlink); | 199 | inode->i_sb->s_id, inode->i_ino, |
200 | inode->i_nlink); | ||
192 | inode->i_nlink = 1; | 201 | inode->i_nlink = 1; |
193 | } | 202 | } |
194 | de->ino = 0; | 203 | de->ino = 0; |
@@ -205,12 +214,12 @@ out_brelse: | |||
205 | return error; | 214 | return error; |
206 | } | 215 | } |
207 | 216 | ||
208 | static int bfs_rename(struct inode * old_dir, struct dentry * old_dentry, | 217 | static int bfs_rename(struct inode *old_dir, struct dentry *old_dentry, |
209 | struct inode * new_dir, struct dentry * new_dentry) | 218 | struct inode *new_dir, struct dentry *new_dentry) |
210 | { | 219 | { |
211 | struct inode * old_inode, * new_inode; | 220 | struct inode *old_inode, *new_inode; |
212 | struct buffer_head * old_bh, * new_bh; | 221 | struct buffer_head *old_bh, *new_bh; |
213 | struct bfs_dirent * old_de, * new_de; | 222 | struct bfs_dirent *old_de, *new_de; |
214 | int error = -ENOENT; | 223 | int error = -ENOENT; |
215 | 224 | ||
216 | old_bh = new_bh = NULL; | 225 | old_bh = new_bh = NULL; |
@@ -223,7 +232,7 @@ static int bfs_rename(struct inode * old_dir, struct dentry * old_dentry, | |||
223 | old_dentry->d_name.name, | 232 | old_dentry->d_name.name, |
224 | old_dentry->d_name.len, &old_de); | 233 | old_dentry->d_name.len, &old_de); |
225 | 234 | ||
226 | if (!old_bh || le16_to_cpu(old_de->ino) != old_inode->i_ino) | 235 | if (!old_bh || (le16_to_cpu(old_de->ino) != old_inode->i_ino)) |
227 | goto end_rename; | 236 | goto end_rename; |
228 | 237 | ||
229 | error = -EPERM; | 238 | error = -EPERM; |
@@ -239,7 +248,8 @@ static int bfs_rename(struct inode * old_dir, struct dentry * old_dentry, | |||
239 | if (!new_bh) { | 248 | if (!new_bh) { |
240 | error = bfs_add_entry(new_dir, | 249 | error = bfs_add_entry(new_dir, |
241 | new_dentry->d_name.name, | 250 | new_dentry->d_name.name, |
242 | new_dentry->d_name.len, old_inode->i_ino); | 251 | new_dentry->d_name.len, |
252 | old_inode->i_ino); | ||
243 | if (error) | 253 | if (error) |
244 | goto end_rename; | 254 | goto end_rename; |
245 | } | 255 | } |
@@ -268,11 +278,12 @@ const struct inode_operations bfs_dir_inops = { | |||
268 | .rename = bfs_rename, | 278 | .rename = bfs_rename, |
269 | }; | 279 | }; |
270 | 280 | ||
271 | static int bfs_add_entry(struct inode * dir, const unsigned char * name, int namelen, int ino) | 281 | static int bfs_add_entry(struct inode *dir, const unsigned char *name, |
282 | int namelen, int ino) | ||
272 | { | 283 | { |
273 | struct buffer_head * bh; | 284 | struct buffer_head *bh; |
274 | struct bfs_dirent * de; | 285 | struct bfs_dirent *de; |
275 | int block, sblock, eblock, off, eoff; | 286 | int block, sblock, eblock, off, pos; |
276 | int i; | 287 | int i; |
277 | 288 | ||
278 | dprintf("name=%s, namelen=%d\n", name, namelen); | 289 | dprintf("name=%s, namelen=%d\n", name, namelen); |
@@ -284,27 +295,24 @@ static int bfs_add_entry(struct inode * dir, const unsigned char * name, int nam | |||
284 | 295 | ||
285 | sblock = BFS_I(dir)->i_sblock; | 296 | sblock = BFS_I(dir)->i_sblock; |
286 | eblock = BFS_I(dir)->i_eblock; | 297 | eblock = BFS_I(dir)->i_eblock; |
287 | eoff = dir->i_size % BFS_BSIZE; | 298 | for (block = sblock; block <= eblock; block++) { |
288 | for (block=sblock; block<=eblock; block++) { | ||
289 | bh = sb_bread(dir->i_sb, block); | 299 | bh = sb_bread(dir->i_sb, block); |
290 | if(!bh) | 300 | if (!bh) |
291 | return -ENOSPC; | 301 | return -ENOSPC; |
292 | for (off=0; off<BFS_BSIZE; off+=BFS_DIRENT_SIZE) { | 302 | for (off = 0; off < BFS_BSIZE; off += BFS_DIRENT_SIZE) { |
293 | de = (struct bfs_dirent *)(bh->b_data + off); | 303 | de = (struct bfs_dirent *)(bh->b_data + off); |
294 | if (block==eblock && off>=eoff) { | ||
295 | /* Do not read/interpret the garbage in the end of eblock. */ | ||
296 | de->ino = 0; | ||
297 | } | ||
298 | if (!de->ino) { | 304 | if (!de->ino) { |
299 | if ((block-sblock)*BFS_BSIZE + off >= dir->i_size) { | 305 | pos = (block - sblock) * BFS_BSIZE + off; |
306 | if (pos >= dir->i_size) { | ||
300 | dir->i_size += BFS_DIRENT_SIZE; | 307 | dir->i_size += BFS_DIRENT_SIZE; |
301 | dir->i_ctime = CURRENT_TIME_SEC; | 308 | dir->i_ctime = CURRENT_TIME_SEC; |
302 | } | 309 | } |
303 | dir->i_mtime = CURRENT_TIME_SEC; | 310 | dir->i_mtime = CURRENT_TIME_SEC; |
304 | mark_inode_dirty(dir); | 311 | mark_inode_dirty(dir); |
305 | de->ino = cpu_to_le16((u16)ino); | 312 | de->ino = cpu_to_le16((u16)ino); |
306 | for (i=0; i<BFS_NAMELEN; i++) | 313 | for (i = 0; i < BFS_NAMELEN; i++) |
307 | de->name[i] = (i < namelen) ? name[i] : 0; | 314 | de->name[i] = |
315 | (i < namelen) ? name[i] : 0; | ||
308 | mark_buffer_dirty(bh); | 316 | mark_buffer_dirty(bh); |
309 | brelse(bh); | 317 | brelse(bh); |
310 | return 0; | 318 | return 0; |
@@ -315,25 +323,26 @@ static int bfs_add_entry(struct inode * dir, const unsigned char * name, int nam | |||
315 | return -ENOSPC; | 323 | return -ENOSPC; |
316 | } | 324 | } |
317 | 325 | ||
318 | static inline int bfs_namecmp(int len, const unsigned char * name, const char * buffer) | 326 | static inline int bfs_namecmp(int len, const unsigned char *name, |
327 | const char *buffer) | ||
319 | { | 328 | { |
320 | if (len < BFS_NAMELEN && buffer[len]) | 329 | if ((len < BFS_NAMELEN) && buffer[len]) |
321 | return 0; | 330 | return 0; |
322 | return !memcmp(name, buffer, len); | 331 | return !memcmp(name, buffer, len); |
323 | } | 332 | } |
324 | 333 | ||
325 | static struct buffer_head * bfs_find_entry(struct inode * dir, | 334 | static struct buffer_head *bfs_find_entry(struct inode *dir, |
326 | const unsigned char * name, int namelen, struct bfs_dirent ** res_dir) | 335 | const unsigned char *name, int namelen, |
336 | struct bfs_dirent **res_dir) | ||
327 | { | 337 | { |
328 | unsigned long block, offset; | 338 | unsigned long block = 0, offset = 0; |
329 | struct buffer_head * bh; | 339 | struct buffer_head *bh = NULL; |
330 | struct bfs_dirent * de; | 340 | struct bfs_dirent *de; |
331 | 341 | ||
332 | *res_dir = NULL; | 342 | *res_dir = NULL; |
333 | if (namelen > BFS_NAMELEN) | 343 | if (namelen > BFS_NAMELEN) |
334 | return NULL; | 344 | return NULL; |
335 | bh = NULL; | 345 | |
336 | block = offset = 0; | ||
337 | while (block * BFS_BSIZE + offset < dir->i_size) { | 346 | while (block * BFS_BSIZE + offset < dir->i_size) { |
338 | if (!bh) { | 347 | if (!bh) { |
339 | bh = sb_bread(dir->i_sb, BFS_I(dir)->i_sblock + block); | 348 | bh = sb_bread(dir->i_sb, BFS_I(dir)->i_sblock + block); |
@@ -344,7 +353,8 @@ static struct buffer_head * bfs_find_entry(struct inode * dir, | |||
344 | } | 353 | } |
345 | de = (struct bfs_dirent *)(bh->b_data + offset); | 354 | de = (struct bfs_dirent *)(bh->b_data + offset); |
346 | offset += BFS_DIRENT_SIZE; | 355 | offset += BFS_DIRENT_SIZE; |
347 | if (le16_to_cpu(de->ino) && bfs_namecmp(namelen, name, de->name)) { | 356 | if (le16_to_cpu(de->ino) && |
357 | bfs_namecmp(namelen, name, de->name)) { | ||
348 | *res_dir = de; | 358 | *res_dir = de; |
349 | return bh; | 359 | return bh; |
350 | } | 360 | } |
diff --git a/fs/bfs/file.c b/fs/bfs/file.c index 911b4ccf470f..b11e63e8fbcd 100644 --- a/fs/bfs/file.c +++ b/fs/bfs/file.c | |||
@@ -2,6 +2,11 @@ | |||
2 | * fs/bfs/file.c | 2 | * fs/bfs/file.c |
3 | * BFS file operations. | 3 | * BFS file operations. |
4 | * Copyright (C) 1999,2000 Tigran Aivazian <tigran@veritas.com> | 4 | * Copyright (C) 1999,2000 Tigran Aivazian <tigran@veritas.com> |
5 | * | ||
6 | * Make the file block allocation algorithm understand the size | ||
7 | * of the underlying block device. | ||
8 | * Copyright (C) 2007 Dmitri Vorobiev <dmitri.vorobiev@gmail.com> | ||
9 | * | ||
5 | */ | 10 | */ |
6 | 11 | ||
7 | #include <linux/fs.h> | 12 | #include <linux/fs.h> |
@@ -27,7 +32,8 @@ const struct file_operations bfs_file_operations = { | |||
27 | .splice_read = generic_file_splice_read, | 32 | .splice_read = generic_file_splice_read, |
28 | }; | 33 | }; |
29 | 34 | ||
30 | static int bfs_move_block(unsigned long from, unsigned long to, struct super_block *sb) | 35 | static int bfs_move_block(unsigned long from, unsigned long to, |
36 | struct super_block *sb) | ||
31 | { | 37 | { |
32 | struct buffer_head *bh, *new; | 38 | struct buffer_head *bh, *new; |
33 | 39 | ||
@@ -43,21 +49,22 @@ static int bfs_move_block(unsigned long from, unsigned long to, struct super_blo | |||
43 | } | 49 | } |
44 | 50 | ||
45 | static int bfs_move_blocks(struct super_block *sb, unsigned long start, | 51 | static int bfs_move_blocks(struct super_block *sb, unsigned long start, |
46 | unsigned long end, unsigned long where) | 52 | unsigned long end, unsigned long where) |
47 | { | 53 | { |
48 | unsigned long i; | 54 | unsigned long i; |
49 | 55 | ||
50 | dprintf("%08lx-%08lx->%08lx\n", start, end, where); | 56 | dprintf("%08lx-%08lx->%08lx\n", start, end, where); |
51 | for (i = start; i <= end; i++) | 57 | for (i = start; i <= end; i++) |
52 | if(bfs_move_block(i, where + i, sb)) { | 58 | if(bfs_move_block(i, where + i, sb)) { |
53 | dprintf("failed to move block %08lx -> %08lx\n", i, where + i); | 59 | dprintf("failed to move block %08lx -> %08lx\n", i, |
60 | where + i); | ||
54 | return -EIO; | 61 | return -EIO; |
55 | } | 62 | } |
56 | return 0; | 63 | return 0; |
57 | } | 64 | } |
58 | 65 | ||
59 | static int bfs_get_block(struct inode * inode, sector_t block, | 66 | static int bfs_get_block(struct inode *inode, sector_t block, |
60 | struct buffer_head * bh_result, int create) | 67 | struct buffer_head *bh_result, int create) |
61 | { | 68 | { |
62 | unsigned long phys; | 69 | unsigned long phys; |
63 | int err; | 70 | int err; |
@@ -66,9 +73,6 @@ static int bfs_get_block(struct inode * inode, sector_t block, | |||
66 | struct bfs_inode_info *bi = BFS_I(inode); | 73 | struct bfs_inode_info *bi = BFS_I(inode); |
67 | struct buffer_head *sbh = info->si_sbh; | 74 | struct buffer_head *sbh = info->si_sbh; |
68 | 75 | ||
69 | if (block > info->si_blocks) | ||
70 | return -EIO; | ||
71 | |||
72 | phys = bi->i_sblock + block; | 76 | phys = bi->i_sblock + block; |
73 | if (!create) { | 77 | if (!create) { |
74 | if (phys <= bi->i_eblock) { | 78 | if (phys <= bi->i_eblock) { |
@@ -79,21 +83,29 @@ static int bfs_get_block(struct inode * inode, sector_t block, | |||
79 | return 0; | 83 | return 0; |
80 | } | 84 | } |
81 | 85 | ||
82 | /* if the file is not empty and the requested block is within the range | 86 | /* |
83 | of blocks allocated for this file, we can grant it */ | 87 | * If the file is not empty and the requested block is within the |
84 | if (inode->i_size && phys <= bi->i_eblock) { | 88 | * range of blocks allocated for this file, we can grant it. |
89 | */ | ||
90 | if (bi->i_sblock && (phys <= bi->i_eblock)) { | ||
85 | dprintf("c=%d, b=%08lx, phys=%08lx (interim block granted)\n", | 91 | dprintf("c=%d, b=%08lx, phys=%08lx (interim block granted)\n", |
86 | create, (unsigned long)block, phys); | 92 | create, (unsigned long)block, phys); |
87 | map_bh(bh_result, sb, phys); | 93 | map_bh(bh_result, sb, phys); |
88 | return 0; | 94 | return 0; |
89 | } | 95 | } |
90 | 96 | ||
91 | /* the rest has to be protected against itself */ | 97 | /* The file will be extended, so let's see if there is enough space. */ |
98 | if (phys >= info->si_blocks) | ||
99 | return -ENOSPC; | ||
100 | |||
101 | /* The rest has to be protected against itself. */ | ||
92 | lock_kernel(); | 102 | lock_kernel(); |
93 | 103 | ||
94 | /* if the last data block for this file is the last allocated | 104 | /* |
95 | block, we can extend the file trivially, without moving it | 105 | * If the last data block for this file is the last allocated |
96 | anywhere */ | 106 | * block, we can extend the file trivially, without moving it |
107 | * anywhere. | ||
108 | */ | ||
97 | if (bi->i_eblock == info->si_lf_eblk) { | 109 | if (bi->i_eblock == info->si_lf_eblk) { |
98 | dprintf("c=%d, b=%08lx, phys=%08lx (simple extension)\n", | 110 | dprintf("c=%d, b=%08lx, phys=%08lx (simple extension)\n", |
99 | create, (unsigned long)block, phys); | 111 | create, (unsigned long)block, phys); |
@@ -106,13 +118,19 @@ static int bfs_get_block(struct inode * inode, sector_t block, | |||
106 | goto out; | 118 | goto out; |
107 | } | 119 | } |
108 | 120 | ||
109 | /* Ok, we have to move this entire file to the next free block */ | 121 | /* Ok, we have to move this entire file to the next free block. */ |
110 | phys = info->si_lf_eblk + 1; | 122 | phys = info->si_lf_eblk + 1; |
111 | if (bi->i_sblock) { /* if data starts on block 0 then there is no data */ | 123 | if (phys + block >= info->si_blocks) { |
124 | err = -ENOSPC; | ||
125 | goto out; | ||
126 | } | ||
127 | |||
128 | if (bi->i_sblock) { | ||
112 | err = bfs_move_blocks(inode->i_sb, bi->i_sblock, | 129 | err = bfs_move_blocks(inode->i_sb, bi->i_sblock, |
113 | bi->i_eblock, phys); | 130 | bi->i_eblock, phys); |
114 | if (err) { | 131 | if (err) { |
115 | dprintf("failed to move ino=%08lx -> fs corruption\n", inode->i_ino); | 132 | dprintf("failed to move ino=%08lx -> fs corruption\n", |
133 | inode->i_ino); | ||
116 | goto out; | 134 | goto out; |
117 | } | 135 | } |
118 | } else | 136 | } else |
@@ -124,8 +142,10 @@ static int bfs_get_block(struct inode * inode, sector_t block, | |||
124 | phys += block; | 142 | phys += block; |
125 | info->si_lf_eblk = bi->i_eblock = phys; | 143 | info->si_lf_eblk = bi->i_eblock = phys; |
126 | 144 | ||
127 | /* this assumes nothing can write the inode back while we are here | 145 | /* |
128 | * and thus update inode->i_blocks! (XXX)*/ | 146 | * This assumes nothing can write the inode back while we are here |
147 | * and thus update inode->i_blocks! (XXX) | ||
148 | */ | ||
129 | info->si_freeb -= bi->i_eblock - bi->i_sblock + 1 - inode->i_blocks; | 149 | info->si_freeb -= bi->i_eblock - bi->i_sblock + 1 - inode->i_blocks; |
130 | mark_inode_dirty(inode); | 150 | mark_inode_dirty(inode); |
131 | mark_buffer_dirty(sbh); | 151 | mark_buffer_dirty(sbh); |
diff --git a/fs/bfs/inode.c b/fs/bfs/inode.c index 7bd9c2bbe6ee..a64a71d444f5 100644 --- a/fs/bfs/inode.c +++ b/fs/bfs/inode.c | |||
@@ -30,25 +30,26 @@ MODULE_LICENSE("GPL"); | |||
30 | #define dprintf(x...) | 30 | #define dprintf(x...) |
31 | #endif | 31 | #endif |
32 | 32 | ||
33 | void dump_imap(const char *prefix, struct super_block * s); | 33 | void dump_imap(const char *prefix, struct super_block *s); |
34 | 34 | ||
35 | static void bfs_read_inode(struct inode * inode) | 35 | static void bfs_read_inode(struct inode *inode) |
36 | { | 36 | { |
37 | unsigned long ino = inode->i_ino; | 37 | unsigned long ino = inode->i_ino; |
38 | struct bfs_inode * di; | 38 | struct bfs_inode *di; |
39 | struct buffer_head * bh; | 39 | struct buffer_head *bh; |
40 | int block, off; | 40 | int block, off; |
41 | 41 | ||
42 | if (ino < BFS_ROOT_INO || ino > BFS_SB(inode->i_sb)->si_lasti) { | 42 | if ((ino < BFS_ROOT_INO) || (ino > BFS_SB(inode->i_sb)->si_lasti)) { |
43 | printf("Bad inode number %s:%08lx\n", inode->i_sb->s_id, ino); | 43 | printf("Bad inode number %s:%08lx\n", inode->i_sb->s_id, ino); |
44 | make_bad_inode(inode); | 44 | make_bad_inode(inode); |
45 | return; | 45 | return; |
46 | } | 46 | } |
47 | 47 | ||
48 | block = (ino - BFS_ROOT_INO)/BFS_INODES_PER_BLOCK + 1; | 48 | block = (ino - BFS_ROOT_INO) / BFS_INODES_PER_BLOCK + 1; |
49 | bh = sb_bread(inode->i_sb, block); | 49 | bh = sb_bread(inode->i_sb, block); |
50 | if (!bh) { | 50 | if (!bh) { |
51 | printf("Unable to read inode %s:%08lx\n", inode->i_sb->s_id, ino); | 51 | printf("Unable to read inode %s:%08lx\n", inode->i_sb->s_id, |
52 | ino); | ||
52 | make_bad_inode(inode); | 53 | make_bad_inode(inode); |
53 | return; | 54 | return; |
54 | } | 55 | } |
@@ -56,7 +57,7 @@ static void bfs_read_inode(struct inode * inode) | |||
56 | off = (ino - BFS_ROOT_INO) % BFS_INODES_PER_BLOCK; | 57 | off = (ino - BFS_ROOT_INO) % BFS_INODES_PER_BLOCK; |
57 | di = (struct bfs_inode *)bh->b_data + off; | 58 | di = (struct bfs_inode *)bh->b_data + off; |
58 | 59 | ||
59 | inode->i_mode = 0x0000FFFF & le32_to_cpu(di->i_mode); | 60 | inode->i_mode = 0x0000FFFF & le32_to_cpu(di->i_mode); |
60 | if (le32_to_cpu(di->i_vtype) == BFS_VDIR) { | 61 | if (le32_to_cpu(di->i_vtype) == BFS_VDIR) { |
61 | inode->i_mode |= S_IFDIR; | 62 | inode->i_mode |= S_IFDIR; |
62 | inode->i_op = &bfs_dir_inops; | 63 | inode->i_op = &bfs_dir_inops; |
@@ -70,48 +71,48 @@ static void bfs_read_inode(struct inode * inode) | |||
70 | 71 | ||
71 | BFS_I(inode)->i_sblock = le32_to_cpu(di->i_sblock); | 72 | BFS_I(inode)->i_sblock = le32_to_cpu(di->i_sblock); |
72 | BFS_I(inode)->i_eblock = le32_to_cpu(di->i_eblock); | 73 | BFS_I(inode)->i_eblock = le32_to_cpu(di->i_eblock); |
74 | BFS_I(inode)->i_dsk_ino = le16_to_cpu(di->i_ino); | ||
73 | inode->i_uid = le32_to_cpu(di->i_uid); | 75 | inode->i_uid = le32_to_cpu(di->i_uid); |
74 | inode->i_gid = le32_to_cpu(di->i_gid); | 76 | inode->i_gid = le32_to_cpu(di->i_gid); |
75 | inode->i_nlink = le32_to_cpu(di->i_nlink); | 77 | inode->i_nlink = le32_to_cpu(di->i_nlink); |
76 | inode->i_size = BFS_FILESIZE(di); | 78 | inode->i_size = BFS_FILESIZE(di); |
77 | inode->i_blocks = BFS_FILEBLOCKS(di); | 79 | inode->i_blocks = BFS_FILEBLOCKS(di); |
78 | if (inode->i_size || inode->i_blocks) dprintf("Registered inode with %lld size, %ld blocks\n", inode->i_size, inode->i_blocks); | ||
79 | inode->i_atime.tv_sec = le32_to_cpu(di->i_atime); | 80 | inode->i_atime.tv_sec = le32_to_cpu(di->i_atime); |
80 | inode->i_mtime.tv_sec = le32_to_cpu(di->i_mtime); | 81 | inode->i_mtime.tv_sec = le32_to_cpu(di->i_mtime); |
81 | inode->i_ctime.tv_sec = le32_to_cpu(di->i_ctime); | 82 | inode->i_ctime.tv_sec = le32_to_cpu(di->i_ctime); |
82 | inode->i_atime.tv_nsec = 0; | 83 | inode->i_atime.tv_nsec = 0; |
83 | inode->i_mtime.tv_nsec = 0; | 84 | inode->i_mtime.tv_nsec = 0; |
84 | inode->i_ctime.tv_nsec = 0; | 85 | inode->i_ctime.tv_nsec = 0; |
85 | BFS_I(inode)->i_dsk_ino = le16_to_cpu(di->i_ino); /* can be 0 so we store a copy */ | ||
86 | 86 | ||
87 | brelse(bh); | 87 | brelse(bh); |
88 | } | 88 | } |
89 | 89 | ||
90 | static int bfs_write_inode(struct inode * inode, int unused) | 90 | static int bfs_write_inode(struct inode *inode, int unused) |
91 | { | 91 | { |
92 | unsigned int ino = (u16)inode->i_ino; | 92 | unsigned int ino = (u16)inode->i_ino; |
93 | unsigned long i_sblock; | 93 | unsigned long i_sblock; |
94 | struct bfs_inode * di; | 94 | struct bfs_inode *di; |
95 | struct buffer_head * bh; | 95 | struct buffer_head *bh; |
96 | int block, off; | 96 | int block, off; |
97 | 97 | ||
98 | dprintf("ino=%08x\n", ino); | 98 | dprintf("ino=%08x\n", ino); |
99 | 99 | ||
100 | if (ino < BFS_ROOT_INO || ino > BFS_SB(inode->i_sb)->si_lasti) { | 100 | if ((ino < BFS_ROOT_INO) || (ino > BFS_SB(inode->i_sb)->si_lasti)) { |
101 | printf("Bad inode number %s:%08x\n", inode->i_sb->s_id, ino); | 101 | printf("Bad inode number %s:%08x\n", inode->i_sb->s_id, ino); |
102 | return -EIO; | 102 | return -EIO; |
103 | } | 103 | } |
104 | 104 | ||
105 | lock_kernel(); | 105 | lock_kernel(); |
106 | block = (ino - BFS_ROOT_INO)/BFS_INODES_PER_BLOCK + 1; | 106 | block = (ino - BFS_ROOT_INO) / BFS_INODES_PER_BLOCK + 1; |
107 | bh = sb_bread(inode->i_sb, block); | 107 | bh = sb_bread(inode->i_sb, block); |
108 | if (!bh) { | 108 | if (!bh) { |
109 | printf("Unable to read inode %s:%08x\n", inode->i_sb->s_id, ino); | 109 | printf("Unable to read inode %s:%08x\n", |
110 | inode->i_sb->s_id, ino); | ||
110 | unlock_kernel(); | 111 | unlock_kernel(); |
111 | return -EIO; | 112 | return -EIO; |
112 | } | 113 | } |
113 | 114 | ||
114 | off = (ino - BFS_ROOT_INO)%BFS_INODES_PER_BLOCK; | 115 | off = (ino - BFS_ROOT_INO) % BFS_INODES_PER_BLOCK; |
115 | di = (struct bfs_inode *)bh->b_data + off; | 116 | di = (struct bfs_inode *)bh->b_data + off; |
116 | 117 | ||
117 | if (ino == BFS_ROOT_INO) | 118 | if (ino == BFS_ROOT_INO) |
@@ -133,27 +134,26 @@ static int bfs_write_inode(struct inode * inode, int unused) | |||
133 | di->i_eoffset = cpu_to_le32(i_sblock * BFS_BSIZE + inode->i_size - 1); | 134 | di->i_eoffset = cpu_to_le32(i_sblock * BFS_BSIZE + inode->i_size - 1); |
134 | 135 | ||
135 | mark_buffer_dirty(bh); | 136 | mark_buffer_dirty(bh); |
136 | dprintf("Written ino=%d into %d:%d\n",le16_to_cpu(di->i_ino),block,off); | ||
137 | brelse(bh); | 137 | brelse(bh); |
138 | unlock_kernel(); | 138 | unlock_kernel(); |
139 | return 0; | 139 | return 0; |
140 | } | 140 | } |
141 | 141 | ||
142 | static void bfs_delete_inode(struct inode * inode) | 142 | static void bfs_delete_inode(struct inode *inode) |
143 | { | 143 | { |
144 | unsigned long ino = inode->i_ino; | 144 | unsigned long ino = inode->i_ino; |
145 | struct bfs_inode * di; | 145 | struct bfs_inode *di; |
146 | struct buffer_head * bh; | 146 | struct buffer_head *bh; |
147 | int block, off; | 147 | int block, off; |
148 | struct super_block * s = inode->i_sb; | 148 | struct super_block *s = inode->i_sb; |
149 | struct bfs_sb_info * info = BFS_SB(s); | 149 | struct bfs_sb_info *info = BFS_SB(s); |
150 | struct bfs_inode_info * bi = BFS_I(inode); | 150 | struct bfs_inode_info *bi = BFS_I(inode); |
151 | 151 | ||
152 | dprintf("ino=%08lx\n", ino); | 152 | dprintf("ino=%08lx\n", ino); |
153 | 153 | ||
154 | truncate_inode_pages(&inode->i_data, 0); | 154 | truncate_inode_pages(&inode->i_data, 0); |
155 | 155 | ||
156 | if (ino < BFS_ROOT_INO || ino > info->si_lasti) { | 156 | if ((ino < BFS_ROOT_INO) || (ino > info->si_lasti)) { |
157 | printf("invalid ino=%08lx\n", ino); | 157 | printf("invalid ino=%08lx\n", ino); |
158 | return; | 158 | return; |
159 | } | 159 | } |
@@ -162,31 +162,36 @@ static void bfs_delete_inode(struct inode * inode) | |||
162 | inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC; | 162 | inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC; |
163 | lock_kernel(); | 163 | lock_kernel(); |
164 | mark_inode_dirty(inode); | 164 | mark_inode_dirty(inode); |
165 | block = (ino - BFS_ROOT_INO)/BFS_INODES_PER_BLOCK + 1; | 165 | |
166 | block = (ino - BFS_ROOT_INO) / BFS_INODES_PER_BLOCK + 1; | ||
166 | bh = sb_bread(s, block); | 167 | bh = sb_bread(s, block); |
167 | if (!bh) { | 168 | if (!bh) { |
168 | printf("Unable to read inode %s:%08lx\n", inode->i_sb->s_id, ino); | 169 | printf("Unable to read inode %s:%08lx\n", |
170 | inode->i_sb->s_id, ino); | ||
169 | unlock_kernel(); | 171 | unlock_kernel(); |
170 | return; | 172 | return; |
171 | } | 173 | } |
172 | off = (ino - BFS_ROOT_INO)%BFS_INODES_PER_BLOCK; | 174 | off = (ino - BFS_ROOT_INO) % BFS_INODES_PER_BLOCK; |
173 | di = (struct bfs_inode *) bh->b_data + off; | 175 | di = (struct bfs_inode *)bh->b_data + off; |
176 | memset((void *)di, 0, sizeof(struct bfs_inode)); | ||
177 | mark_buffer_dirty(bh); | ||
178 | brelse(bh); | ||
179 | |||
174 | if (bi->i_dsk_ino) { | 180 | if (bi->i_dsk_ino) { |
175 | info->si_freeb += 1 + bi->i_eblock - bi->i_sblock; | 181 | if (bi->i_sblock) |
182 | info->si_freeb += bi->i_eblock + 1 - bi->i_sblock; | ||
176 | info->si_freei++; | 183 | info->si_freei++; |
177 | clear_bit(ino, info->si_imap); | 184 | clear_bit(ino, info->si_imap); |
178 | dump_imap("delete_inode", s); | 185 | dump_imap("delete_inode", s); |
179 | } | 186 | } |
180 | di->i_ino = 0; | ||
181 | di->i_sblock = 0; | ||
182 | mark_buffer_dirty(bh); | ||
183 | brelse(bh); | ||
184 | 187 | ||
185 | /* if this was the last file, make the previous | 188 | /* |
186 | block "last files last block" even if there is no real file there, | 189 | * If this was the last file, make the previous block |
187 | saves us 1 gap */ | 190 | * "last block of the last file" even if there is no |
188 | if (info->si_lf_eblk == BFS_I(inode)->i_eblock) { | 191 | * real file there, saves us 1 gap. |
189 | info->si_lf_eblk = BFS_I(inode)->i_sblock - 1; | 192 | */ |
193 | if (info->si_lf_eblk == bi->i_eblock) { | ||
194 | info->si_lf_eblk = bi->i_sblock - 1; | ||
190 | mark_buffer_dirty(info->si_sbh); | 195 | mark_buffer_dirty(info->si_sbh); |
191 | } | 196 | } |
192 | unlock_kernel(); | 197 | unlock_kernel(); |
@@ -228,7 +233,7 @@ static void bfs_write_super(struct super_block *s) | |||
228 | unlock_kernel(); | 233 | unlock_kernel(); |
229 | } | 234 | } |
230 | 235 | ||
231 | static struct kmem_cache * bfs_inode_cachep; | 236 | static struct kmem_cache *bfs_inode_cachep; |
232 | 237 | ||
233 | static struct inode *bfs_alloc_inode(struct super_block *sb) | 238 | static struct inode *bfs_alloc_inode(struct super_block *sb) |
234 | { | 239 | { |
@@ -279,7 +284,7 @@ static const struct super_operations bfs_sops = { | |||
279 | .statfs = bfs_statfs, | 284 | .statfs = bfs_statfs, |
280 | }; | 285 | }; |
281 | 286 | ||
282 | void dump_imap(const char *prefix, struct super_block * s) | 287 | void dump_imap(const char *prefix, struct super_block *s) |
283 | { | 288 | { |
284 | #ifdef DEBUG | 289 | #ifdef DEBUG |
285 | int i; | 290 | int i; |
@@ -287,25 +292,26 @@ void dump_imap(const char *prefix, struct super_block * s) | |||
287 | 292 | ||
288 | if (!tmpbuf) | 293 | if (!tmpbuf) |
289 | return; | 294 | return; |
290 | for (i=BFS_SB(s)->si_lasti; i>=0; i--) { | 295 | for (i = BFS_SB(s)->si_lasti; i >= 0; i--) { |
291 | if (i > PAGE_SIZE-100) break; | 296 | if (i > PAGE_SIZE - 100) break; |
292 | if (test_bit(i, BFS_SB(s)->si_imap)) | 297 | if (test_bit(i, BFS_SB(s)->si_imap)) |
293 | strcat(tmpbuf, "1"); | 298 | strcat(tmpbuf, "1"); |
294 | else | 299 | else |
295 | strcat(tmpbuf, "0"); | 300 | strcat(tmpbuf, "0"); |
296 | } | 301 | } |
297 | printk(KERN_ERR "BFS-fs: %s: lasti=%08lx <%s>\n", prefix, BFS_SB(s)->si_lasti, tmpbuf); | 302 | printf("BFS-fs: %s: lasti=%08lx <%s>\n", |
303 | prefix, BFS_SB(s)->si_lasti, tmpbuf); | ||
298 | free_page((unsigned long)tmpbuf); | 304 | free_page((unsigned long)tmpbuf); |
299 | #endif | 305 | #endif |
300 | } | 306 | } |
301 | 307 | ||
302 | static int bfs_fill_super(struct super_block *s, void *data, int silent) | 308 | static int bfs_fill_super(struct super_block *s, void *data, int silent) |
303 | { | 309 | { |
304 | struct buffer_head * bh; | 310 | struct buffer_head *bh; |
305 | struct bfs_super_block * bfs_sb; | 311 | struct bfs_super_block *bfs_sb; |
306 | struct inode * inode; | 312 | struct inode *inode; |
307 | unsigned i, imap_len; | 313 | unsigned i, imap_len; |
308 | struct bfs_sb_info * info; | 314 | struct bfs_sb_info *info; |
309 | 315 | ||
310 | info = kzalloc(sizeof(*info), GFP_KERNEL); | 316 | info = kzalloc(sizeof(*info), GFP_KERNEL); |
311 | if (!info) | 317 | if (!info) |
@@ -329,14 +335,14 @@ static int bfs_fill_super(struct super_block *s, void *data, int silent) | |||
329 | 335 | ||
330 | s->s_magic = BFS_MAGIC; | 336 | s->s_magic = BFS_MAGIC; |
331 | info->si_sbh = bh; | 337 | info->si_sbh = bh; |
332 | info->si_lasti = (le32_to_cpu(bfs_sb->s_start) - BFS_BSIZE)/sizeof(struct bfs_inode) | 338 | info->si_lasti = (le32_to_cpu(bfs_sb->s_start) - BFS_BSIZE) / |
333 | + BFS_ROOT_INO - 1; | 339 | sizeof(struct bfs_inode) |
334 | 340 | + BFS_ROOT_INO - 1; | |
335 | imap_len = info->si_lasti/8 + 1; | 341 | imap_len = (info->si_lasti / 8) + 1; |
336 | info->si_imap = kzalloc(imap_len, GFP_KERNEL); | 342 | info->si_imap = kzalloc(imap_len, GFP_KERNEL); |
337 | if (!info->si_imap) | 343 | if (!info->si_imap) |
338 | goto out; | 344 | goto out; |
339 | for (i=0; i<BFS_ROOT_INO; i++) | 345 | for (i = 0; i < BFS_ROOT_INO; i++) |
340 | set_bit(i, info->si_imap); | 346 | set_bit(i, info->si_imap); |
341 | 347 | ||
342 | s->s_op = &bfs_sops; | 348 | s->s_op = &bfs_sops; |
@@ -352,16 +358,15 @@ static int bfs_fill_super(struct super_block *s, void *data, int silent) | |||
352 | goto out; | 358 | goto out; |
353 | } | 359 | } |
354 | 360 | ||
355 | info->si_blocks = (le32_to_cpu(bfs_sb->s_end) + 1)>>BFS_BSIZE_BITS; /* for statfs(2) */ | 361 | info->si_blocks = (le32_to_cpu(bfs_sb->s_end) + 1) >> BFS_BSIZE_BITS; |
356 | info->si_freeb = (le32_to_cpu(bfs_sb->s_end) + 1 - le32_to_cpu(bfs_sb->s_start))>>BFS_BSIZE_BITS; | 362 | info->si_freeb = (le32_to_cpu(bfs_sb->s_end) + 1 |
363 | - le32_to_cpu(bfs_sb->s_start)) >> BFS_BSIZE_BITS; | ||
357 | info->si_freei = 0; | 364 | info->si_freei = 0; |
358 | info->si_lf_eblk = 0; | 365 | info->si_lf_eblk = 0; |
359 | info->si_lf_sblk = 0; | ||
360 | info->si_lf_ioff = 0; | ||
361 | bh = NULL; | 366 | bh = NULL; |
362 | for (i=BFS_ROOT_INO; i<=info->si_lasti; i++) { | 367 | for (i = BFS_ROOT_INO; i <= info->si_lasti; i++) { |
363 | struct bfs_inode *di; | 368 | struct bfs_inode *di; |
364 | int block = (i - BFS_ROOT_INO)/BFS_INODES_PER_BLOCK + 1; | 369 | int block = (i - BFS_ROOT_INO) / BFS_INODES_PER_BLOCK + 1; |
365 | int off = (i - BFS_ROOT_INO) % BFS_INODES_PER_BLOCK; | 370 | int off = (i - BFS_ROOT_INO) % BFS_INODES_PER_BLOCK; |
366 | unsigned long sblock, eblock; | 371 | unsigned long sblock, eblock; |
367 | 372 | ||
@@ -384,11 +389,8 @@ static int bfs_fill_super(struct super_block *s, void *data, int silent) | |||
384 | 389 | ||
385 | sblock = le32_to_cpu(di->i_sblock); | 390 | sblock = le32_to_cpu(di->i_sblock); |
386 | eblock = le32_to_cpu(di->i_eblock); | 391 | eblock = le32_to_cpu(di->i_eblock); |
387 | if (eblock > info->si_lf_eblk) { | 392 | if (eblock > info->si_lf_eblk) |
388 | info->si_lf_eblk = eblock; | 393 | info->si_lf_eblk = eblock; |
389 | info->si_lf_sblk = sblock; | ||
390 | info->si_lf_ioff = BFS_INO2OFF(i); | ||
391 | } | ||
392 | } | 394 | } |
393 | brelse(bh); | 395 | brelse(bh); |
394 | if (!(s->s_flags & MS_RDONLY)) { | 396 | if (!(s->s_flags & MS_RDONLY)) { |
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 6e2f3b8dde7f..ba8de7ca260b 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c | |||
@@ -1383,10 +1383,10 @@ static void fill_prstatus(struct elf_prstatus *prstatus, | |||
1383 | prstatus->pr_info.si_signo = prstatus->pr_cursig = signr; | 1383 | prstatus->pr_info.si_signo = prstatus->pr_cursig = signr; |
1384 | prstatus->pr_sigpend = p->pending.signal.sig[0]; | 1384 | prstatus->pr_sigpend = p->pending.signal.sig[0]; |
1385 | prstatus->pr_sighold = p->blocked.sig[0]; | 1385 | prstatus->pr_sighold = p->blocked.sig[0]; |
1386 | prstatus->pr_pid = p->pid; | 1386 | prstatus->pr_pid = task_pid_vnr(p); |
1387 | prstatus->pr_ppid = p->parent->pid; | 1387 | prstatus->pr_ppid = task_pid_vnr(p->parent); |
1388 | prstatus->pr_pgrp = process_group(p); | 1388 | prstatus->pr_pgrp = task_pgrp_vnr(p); |
1389 | prstatus->pr_sid = process_session(p); | 1389 | prstatus->pr_sid = task_session_vnr(p); |
1390 | if (thread_group_leader(p)) { | 1390 | if (thread_group_leader(p)) { |
1391 | /* | 1391 | /* |
1392 | * This is the record for the group leader. Add in the | 1392 | * This is the record for the group leader. Add in the |
@@ -1429,10 +1429,10 @@ static int fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p, | |||
1429 | psinfo->pr_psargs[i] = ' '; | 1429 | psinfo->pr_psargs[i] = ' '; |
1430 | psinfo->pr_psargs[len] = 0; | 1430 | psinfo->pr_psargs[len] = 0; |
1431 | 1431 | ||
1432 | psinfo->pr_pid = p->pid; | 1432 | psinfo->pr_pid = task_pid_vnr(p); |
1433 | psinfo->pr_ppid = p->parent->pid; | 1433 | psinfo->pr_ppid = task_pid_vnr(p->parent); |
1434 | psinfo->pr_pgrp = process_group(p); | 1434 | psinfo->pr_pgrp = task_pgrp_vnr(p); |
1435 | psinfo->pr_sid = process_session(p); | 1435 | psinfo->pr_sid = task_session_vnr(p); |
1436 | 1436 | ||
1437 | i = p->state ? ffz(~p->state) + 1 : 0; | 1437 | i = p->state ? ffz(~p->state) + 1 : 0; |
1438 | psinfo->pr_state = i; | 1438 | psinfo->pr_state = i; |
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c index 033861c6b8f1..32649f2a1654 100644 --- a/fs/binfmt_elf_fdpic.c +++ b/fs/binfmt_elf_fdpic.c | |||
@@ -1342,10 +1342,10 @@ static void fill_prstatus(struct elf_prstatus *prstatus, | |||
1342 | prstatus->pr_info.si_signo = prstatus->pr_cursig = signr; | 1342 | prstatus->pr_info.si_signo = prstatus->pr_cursig = signr; |
1343 | prstatus->pr_sigpend = p->pending.signal.sig[0]; | 1343 | prstatus->pr_sigpend = p->pending.signal.sig[0]; |
1344 | prstatus->pr_sighold = p->blocked.sig[0]; | 1344 | prstatus->pr_sighold = p->blocked.sig[0]; |
1345 | prstatus->pr_pid = p->pid; | 1345 | prstatus->pr_pid = task_pid_vnr(p); |
1346 | prstatus->pr_ppid = p->parent->pid; | 1346 | prstatus->pr_ppid = task_pid_vnr(p->parent); |
1347 | prstatus->pr_pgrp = process_group(p); | 1347 | prstatus->pr_pgrp = task_pgrp_vnr(p); |
1348 | prstatus->pr_sid = process_session(p); | 1348 | prstatus->pr_sid = task_session_vnr(p); |
1349 | if (thread_group_leader(p)) { | 1349 | if (thread_group_leader(p)) { |
1350 | /* | 1350 | /* |
1351 | * This is the record for the group leader. Add in the | 1351 | * This is the record for the group leader. Add in the |
@@ -1391,10 +1391,10 @@ static int fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p, | |||
1391 | psinfo->pr_psargs[i] = ' '; | 1391 | psinfo->pr_psargs[i] = ' '; |
1392 | psinfo->pr_psargs[len] = 0; | 1392 | psinfo->pr_psargs[len] = 0; |
1393 | 1393 | ||
1394 | psinfo->pr_pid = p->pid; | 1394 | psinfo->pr_pid = task_pid_vnr(p); |
1395 | psinfo->pr_ppid = p->parent->pid; | 1395 | psinfo->pr_ppid = task_pid_vnr(p->parent); |
1396 | psinfo->pr_pgrp = process_group(p); | 1396 | psinfo->pr_pgrp = task_pgrp_vnr(p); |
1397 | psinfo->pr_sid = process_session(p); | 1397 | psinfo->pr_sid = task_session_vnr(p); |
1398 | 1398 | ||
1399 | i = p->state ? ffz(~p->state) + 1 : 0; | 1399 | i = p->state ? ffz(~p->state) + 1 : 0; |
1400 | psinfo->pr_state = i; | 1400 | psinfo->pr_state = i; |
diff --git a/fs/binfmt_em86.c b/fs/binfmt_em86.c index 576dd7de2278..f95ae9789c91 100644 --- a/fs/binfmt_em86.c +++ b/fs/binfmt_em86.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * linux/fs/binfmt_em86.c | 2 | * linux/fs/binfmt_em86.c |
3 | * | 3 | * |
4 | * Based on linux/fs/binfmt_script.c | 4 | * Based on linux/fs/binfmt_script.c |
5 | * Copyright (C) 1996 Martin von Löwis | 5 | * Copyright (C) 1996 Martin von Löwis |
6 | * original #!-checking implemented by tytso. | 6 | * original #!-checking implemented by tytso. |
7 | * | 7 | * |
8 | * em86 changes Copyright (C) 1997 Jim Paradis | 8 | * em86 changes Copyright (C) 1997 Jim Paradis |
diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c index 42e94b3ab7be..b53c7e5f41bb 100644 --- a/fs/binfmt_misc.c +++ b/fs/binfmt_misc.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * binfmt_misc.c | 2 | * binfmt_misc.c |
3 | * | 3 | * |
4 | * Copyright (C) 1997 Richard Günther | 4 | * Copyright (C) 1997 Richard Günther |
5 | * | 5 | * |
6 | * binfmt_misc detects binaries via a magic or filename extension and invokes | 6 | * binfmt_misc detects binaries via a magic or filename extension and invokes |
7 | * a specified wrapper. This should obsolete binfmt_java, binfmt_em86 and | 7 | * a specified wrapper. This should obsolete binfmt_java, binfmt_em86 and |
diff --git a/fs/binfmt_script.c b/fs/binfmt_script.c index 4d0e0f6d3273..ab33939b12a7 100644 --- a/fs/binfmt_script.c +++ b/fs/binfmt_script.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * linux/fs/binfmt_script.c | 2 | * linux/fs/binfmt_script.c |
3 | * | 3 | * |
4 | * Copyright (C) 1996 Martin von Löwis | 4 | * Copyright (C) 1996 Martin von Löwis |
5 | * original #!-checking implemented by tytso. | 5 | * original #!-checking implemented by tytso. |
6 | */ | 6 | */ |
7 | 7 | ||
diff --git a/fs/buffer.c b/fs/buffer.c index 76403b1764c5..7249e014819e 100644 --- a/fs/buffer.c +++ b/fs/buffer.c | |||
@@ -2563,7 +2563,7 @@ int nobh_write_end(struct file *file, struct address_space *mapping, | |||
2563 | struct page *page, void *fsdata) | 2563 | struct page *page, void *fsdata) |
2564 | { | 2564 | { |
2565 | struct inode *inode = page->mapping->host; | 2565 | struct inode *inode = page->mapping->host; |
2566 | struct buffer_head *head = NULL; | 2566 | struct buffer_head *head = fsdata; |
2567 | struct buffer_head *bh; | 2567 | struct buffer_head *bh; |
2568 | 2568 | ||
2569 | if (!PageMappedToDisk(page)) { | 2569 | if (!PageMappedToDisk(page)) { |
@@ -2584,7 +2584,6 @@ int nobh_write_end(struct file *file, struct address_space *mapping, | |||
2584 | unlock_page(page); | 2584 | unlock_page(page); |
2585 | page_cache_release(page); | 2585 | page_cache_release(page); |
2586 | 2586 | ||
2587 | head = fsdata; | ||
2588 | while (head) { | 2587 | while (head) { |
2589 | bh = head; | 2588 | bh = head; |
2590 | head = head->b_this_page; | 2589 | head = head->b_this_page; |
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index bed6215c0794..a609599287aa 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES | |||
@@ -1,3 +1,31 @@ | |||
1 | Version 1.52 | ||
2 | ------------ | ||
3 | Fix oops on second mount to server when null auth is used. | ||
4 | Enable experimental Kerberos support. Return writebehind errors on flush | ||
5 | and sync so that events like out of disk space get reported properly on | ||
6 | cached files. | ||
7 | |||
8 | Version 1.51 | ||
9 | ------------ | ||
10 | Fix memory leak in statfs when mounted to very old servers (e.g. | ||
11 | Windows 9x). Add new feature "POSIX open" which allows servers | ||
12 | which support the current POSIX Extensions to provide better semantics | ||
13 | (e.g. delete for open files opened with posix open). Take into | ||
14 | account umask on posix mkdir not just older style mkdir. Add | ||
15 | ability to mount to IPC$ share (which allows CIFS named pipes to be | ||
16 | opened, read and written as if they were files). When 1st tree | ||
17 | connect fails (e.g. due to signing negotiation failure) fix | ||
18 | leak that causes cifsd not to stop and rmmod to fail to cleanup | ||
19 | cifs_request_buffers pool. Fix problem with POSIX Open/Mkdir on | ||
20 | bigendian architectures. Fix possible memory corruption when | ||
21 | EAGAIN returned on kern_recvmsg. Return better error if server | ||
22 | requires packet signing but client has disabled it. When mounted | ||
23 | with cifsacl mount option - mode bits are approximated based | ||
24 | on the contents of the ACL of the file or directory. When cifs | ||
25 | mount helper is missing convert make sure that UNC name | ||
26 | has backslash (not forward slash) between ip address of server | ||
27 | and the share name. | ||
28 | |||
1 | Version 1.50 | 29 | Version 1.50 |
2 | ------------ | 30 | ------------ |
3 | Fix NTLMv2 signing. NFS server mounted over cifs works (if cifs mount is | 31 | Fix NTLMv2 signing. NFS server mounted over cifs works (if cifs mount is |
@@ -6,7 +34,10 @@ done with "serverino" mount option). Add support for POSIX Unlink | |||
6 | Samba supports newer POSIX CIFS Protocol Extensions). Add "nounix" | 34 | Samba supports newer POSIX CIFS Protocol Extensions). Add "nounix" |
7 | mount option to allow disabling the CIFS Unix Extensions for just | 35 | mount option to allow disabling the CIFS Unix Extensions for just |
8 | that mount. Fix hang on spinlock in find_writable_file (race when | 36 | that mount. Fix hang on spinlock in find_writable_file (race when |
9 | reopening file after session crash). | 37 | reopening file after session crash). Byte range unlock request to |
38 | windows server could unlock more bytes (on server copy of file) | ||
39 | than intended if start of unlock request is well before start of | ||
40 | a previous byte range lock that we issued. | ||
10 | 41 | ||
11 | Version 1.49 | 42 | Version 1.49 |
12 | ------------ | 43 | ------------ |
diff --git a/fs/cifs/Makefile b/fs/cifs/Makefile index 6ecd9d6ba3f3..45e42fb97c19 100644 --- a/fs/cifs/Makefile +++ b/fs/cifs/Makefile | |||
@@ -3,4 +3,9 @@ | |||
3 | # | 3 | # |
4 | obj-$(CONFIG_CIFS) += cifs.o | 4 | obj-$(CONFIG_CIFS) += cifs.o |
5 | 5 | ||
6 | cifs-objs := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o md4.o md5.o cifs_unicode.o nterr.o xattr.o cifsencrypt.o fcntl.o readdir.o ioctl.o sess.o export.o | 6 | cifs-y := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o \ |
7 | link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o \ | ||
8 | md4.o md5.o cifs_unicode.o nterr.o xattr.o cifsencrypt.o fcntl.o \ | ||
9 | readdir.o ioctl.o sess.o export.o cifsacl.o | ||
10 | |||
11 | cifs-$(CONFIG_CIFS_UPCALL) += cifs_spnego.o | ||
diff --git a/fs/cifs/README b/fs/cifs/README index b806b11b5560..bf11329ac784 100644 --- a/fs/cifs/README +++ b/fs/cifs/README | |||
@@ -225,12 +225,9 @@ If no password is provided, mount.cifs will prompt for password entry | |||
225 | 225 | ||
226 | Restrictions | 226 | Restrictions |
227 | ============ | 227 | ============ |
228 | Servers must support the NTLM SMB dialect (which is the most recent, supported | ||
229 | by Samba and Windows NT version 4, 2000 and XP and many other SMB/CIFS servers) | ||
230 | Servers must support either "pure-TCP" (port 445 TCP/IP CIFS connections) or RFC | 228 | Servers must support either "pure-TCP" (port 445 TCP/IP CIFS connections) or RFC |
231 | 1001/1002 support for "Netbios-Over-TCP/IP." Neither of these is likely to be a | 229 | 1001/1002 support for "Netbios-Over-TCP/IP." This is not likely to be a |
232 | problem as most servers support this. IPv6 support is planned for the future, | 230 | problem as most servers support this. |
233 | and is almost complete. | ||
234 | 231 | ||
235 | Valid filenames differ between Windows and Linux. Windows typically restricts | 232 | Valid filenames differ between Windows and Linux. Windows typically restricts |
236 | filenames which contain certain reserved characters (e.g.the character : | 233 | filenames which contain certain reserved characters (e.g.the character : |
@@ -458,6 +455,8 @@ A partial list of the supported mount options follows: | |||
458 | byte range locks). | 455 | byte range locks). |
459 | remount remount the share (often used to change from ro to rw mounts | 456 | remount remount the share (often used to change from ro to rw mounts |
460 | or vice versa) | 457 | or vice versa) |
458 | cifsacl Report mode bits (e.g. on stat) based on the Windows ACL for | ||
459 | the file. (EXPERIMENTAL) | ||
461 | servern Specify the server 's netbios name (RFC1001 name) to use | 460 | servern Specify the server 's netbios name (RFC1001 name) to use |
462 | when attempting to setup a session to the server. This is | 461 | when attempting to setup a session to the server. This is |
463 | This is needed for mounting to some older servers (such | 462 | This is needed for mounting to some older servers (such |
@@ -584,8 +583,8 @@ Experimental When set to 1 used to enable certain experimental | |||
584 | performance enhancement was disabled when | 583 | performance enhancement was disabled when |
585 | signing turned on in case buffer was modified | 584 | signing turned on in case buffer was modified |
586 | just before it was sent, also this flag will | 585 | just before it was sent, also this flag will |
587 | be used to use the new experimental sessionsetup | 586 | be used to use the new experimental directory change |
588 | code). | 587 | notification code). |
589 | 588 | ||
590 | These experimental features and tracing can be enabled by changing flags in | 589 | These experimental features and tracing can be enabled by changing flags in |
591 | /proc/fs/cifs (after the cifs module has been installed or built into the | 590 | /proc/fs/cifs (after the cifs module has been installed or built into the |
@@ -608,7 +607,8 @@ the start of smb requests and responses can be enabled via: | |||
608 | Two other experimental features are under development. To test these | 607 | Two other experimental features are under development. To test these |
609 | requires enabling CONFIG_CIFS_EXPERIMENTAL | 608 | requires enabling CONFIG_CIFS_EXPERIMENTAL |
610 | 609 | ||
611 | ipv6 enablement | 610 | cifsacl support needed to retrieve approximated mode bits based on |
611 | the contents on the CIFS ACL. | ||
612 | 612 | ||
613 | DNOTIFY fcntl: needed for support of directory change | 613 | DNOTIFY fcntl: needed for support of directory change |
614 | notification and perhaps later for file leases) | 614 | notification and perhaps later for file leases) |
@@ -625,10 +625,7 @@ that they represent all for that share, not just those for which the server | |||
625 | returned success. | 625 | returned success. |
626 | 626 | ||
627 | Also note that "cat /proc/fs/cifs/DebugData" will display information about | 627 | Also note that "cat /proc/fs/cifs/DebugData" will display information about |
628 | the active sessions and the shares that are mounted. Note: NTLMv2 enablement | 628 | the active sessions and the shares that are mounted. |
629 | will not work since its implementation is not quite complete yet. Do not alter | 629 | Enabling Kerberos (extended security) works when CONFIG_CIFS_EXPERIMENTAL is enabled |
630 | the ExtendedSecurity configuration value unless you are doing specific testing. | 630 | but requires a user space helper (from the Samba project). NTLM and NTLMv2 and |
631 | Enabling extended security works to Windows 2000 Workstations and XP but not to | 631 | LANMAN support do not require this helpr. |
632 | Windows 2000 server or Samba since it does not usually send "raw NTLMSSP" | ||
633 | (instead it sends NTLMSSP encapsulated in SPNEGO/GSSAPI, which support is not | ||
634 | complete in the CIFS VFS yet). | ||
diff --git a/fs/cifs/TODO b/fs/cifs/TODO index 29d4b2715254..a8852c200728 100644 --- a/fs/cifs/TODO +++ b/fs/cifs/TODO | |||
@@ -16,7 +16,7 @@ SecurityDescriptors | |||
16 | c) Better pam/winbind integration (e.g. to handle uid mapping | 16 | c) Better pam/winbind integration (e.g. to handle uid mapping |
17 | better) | 17 | better) |
18 | 18 | ||
19 | d) Kerberos/SPNEGO session setup support - (started) | 19 | d) Verify that Kerberos signing works |
20 | 20 | ||
21 | e) Cleanup now unneeded SessSetup code in | 21 | e) Cleanup now unneeded SessSetup code in |
22 | fs/cifs/connect.c and add back in NTLMSSP code if any servers | 22 | fs/cifs/connect.c and add back in NTLMSSP code if any servers |
diff --git a/fs/cifs/asn1.c b/fs/cifs/asn1.c index f50a88d58f78..bcda2c6b6a04 100644 --- a/fs/cifs/asn1.c +++ b/fs/cifs/asn1.c | |||
@@ -77,8 +77,12 @@ | |||
77 | 77 | ||
78 | #define SPNEGO_OID_LEN 7 | 78 | #define SPNEGO_OID_LEN 7 |
79 | #define NTLMSSP_OID_LEN 10 | 79 | #define NTLMSSP_OID_LEN 10 |
80 | #define KRB5_OID_LEN 7 | ||
81 | #define MSKRB5_OID_LEN 7 | ||
80 | static unsigned long SPNEGO_OID[7] = { 1, 3, 6, 1, 5, 5, 2 }; | 82 | static unsigned long SPNEGO_OID[7] = { 1, 3, 6, 1, 5, 5, 2 }; |
81 | static unsigned long NTLMSSP_OID[10] = { 1, 3, 6, 1, 4, 1, 311, 2, 2, 10 }; | 83 | static unsigned long NTLMSSP_OID[10] = { 1, 3, 6, 1, 4, 1, 311, 2, 2, 10 }; |
84 | static unsigned long KRB5_OID[7] = { 1, 2, 840, 113554, 1, 2, 2 }; | ||
85 | static unsigned long MSKRB5_OID[7] = { 1, 2, 840, 48018, 1, 2, 2 }; | ||
82 | 86 | ||
83 | /* | 87 | /* |
84 | * ASN.1 context. | 88 | * ASN.1 context. |
@@ -385,10 +389,9 @@ asn1_oid_decode(struct asn1_ctx *ctx, | |||
385 | unsigned long *optr; | 389 | unsigned long *optr; |
386 | 390 | ||
387 | size = eoc - ctx->pointer + 1; | 391 | size = eoc - ctx->pointer + 1; |
388 | *oid = kmalloc(size * sizeof (unsigned long), GFP_ATOMIC); | 392 | *oid = kmalloc(size * sizeof(unsigned long), GFP_ATOMIC); |
389 | if (*oid == NULL) { | 393 | if (*oid == NULL) |
390 | return 0; | 394 | return 0; |
391 | } | ||
392 | 395 | ||
393 | optr = *oid; | 396 | optr = *oid; |
394 | 397 | ||
@@ -458,6 +461,7 @@ decode_negTokenInit(unsigned char *security_blob, int length, | |||
458 | unsigned long *oid = NULL; | 461 | unsigned long *oid = NULL; |
459 | unsigned int cls, con, tag, oidlen, rc; | 462 | unsigned int cls, con, tag, oidlen, rc; |
460 | int use_ntlmssp = FALSE; | 463 | int use_ntlmssp = FALSE; |
464 | int use_kerberos = FALSE; | ||
461 | 465 | ||
462 | *secType = NTLM; /* BB eventually make Kerberos or NLTMSSP the default*/ | 466 | *secType = NTLM; /* BB eventually make Kerberos or NLTMSSP the default*/ |
463 | 467 | ||
@@ -546,18 +550,28 @@ decode_negTokenInit(unsigned char *security_blob, int length, | |||
546 | return 0; | 550 | return 0; |
547 | } | 551 | } |
548 | if ((tag == ASN1_OJI) && (con == ASN1_PRI)) { | 552 | if ((tag == ASN1_OJI) && (con == ASN1_PRI)) { |
549 | rc = asn1_oid_decode(&ctx, end, &oid, &oidlen); | 553 | if (asn1_oid_decode(&ctx, end, &oid, &oidlen)) { |
550 | if (rc) { | 554 | |
551 | cFYI(1, | 555 | cFYI(1, |
552 | ("OID len = %d oid = 0x%lx 0x%lx " | 556 | ("OID len = %d oid = 0x%lx 0x%lx " |
553 | "0x%lx 0x%lx", | 557 | "0x%lx 0x%lx", |
554 | oidlen, *oid, *(oid + 1), | 558 | oidlen, *oid, *(oid + 1), |
555 | *(oid + 2), *(oid + 3))); | 559 | *(oid + 2), *(oid + 3))); |
556 | rc = compare_oid(oid, oidlen, | 560 | |
557 | NTLMSSP_OID, NTLMSSP_OID_LEN); | 561 | if (compare_oid(oid, oidlen, |
558 | kfree(oid); | 562 | MSKRB5_OID, |
559 | if (rc) | 563 | MSKRB5_OID_LEN)) |
564 | use_kerberos = TRUE; | ||
565 | else if (compare_oid(oid, oidlen, | ||
566 | KRB5_OID, | ||
567 | KRB5_OID_LEN)) | ||
568 | use_kerberos = TRUE; | ||
569 | else if (compare_oid(oid, oidlen, | ||
570 | NTLMSSP_OID, | ||
571 | NTLMSSP_OID_LEN)) | ||
560 | use_ntlmssp = TRUE; | 572 | use_ntlmssp = TRUE; |
573 | |||
574 | kfree(oid); | ||
561 | } | 575 | } |
562 | } else { | 576 | } else { |
563 | cFYI(1, ("Should be an oid what is going on?")); | 577 | cFYI(1, ("Should be an oid what is going on?")); |
@@ -581,9 +595,8 @@ decode_negTokenInit(unsigned char *security_blob, int length, | |||
581 | return 0; | 595 | return 0; |
582 | } else if ((cls != ASN1_UNI) || (con != ASN1_CON) | 596 | } else if ((cls != ASN1_UNI) || (con != ASN1_CON) |
583 | || (tag != ASN1_SEQ)) { | 597 | || (tag != ASN1_SEQ)) { |
584 | cFYI(1, | 598 | cFYI(1, ("cls = %d con = %d tag = %d end = %p (%d)", |
585 | ("Exit 6 cls = %d con = %d tag = %d end = %p (%d)", | 599 | cls, con, tag, end, *end)); |
586 | cls, con, tag, end, *end)); | ||
587 | } | 600 | } |
588 | 601 | ||
589 | if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { | 602 | if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { |
@@ -611,12 +624,10 @@ decode_negTokenInit(unsigned char *security_blob, int length, | |||
611 | ctx.pointer)); /* is this UTF-8 or ASCII? */ | 624 | ctx.pointer)); /* is this UTF-8 or ASCII? */ |
612 | } | 625 | } |
613 | 626 | ||
614 | /* if (use_kerberos) | 627 | if (use_kerberos) |
615 | *secType = Kerberos | 628 | *secType = Kerberos; |
616 | else */ | 629 | else if (use_ntlmssp) |
617 | if (use_ntlmssp) { | ||
618 | *secType = NTLMSSP; | 630 | *secType = NTLMSSP; |
619 | } | ||
620 | 631 | ||
621 | return 1; | 632 | return 1; |
622 | } | 633 | } |
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c index 1bf8cf522ad6..73c4c419663c 100644 --- a/fs/cifs/cifs_debug.c +++ b/fs/cifs/cifs_debug.c | |||
@@ -209,13 +209,16 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset, | |||
209 | i++; | 209 | i++; |
210 | tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList); | 210 | tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList); |
211 | dev_type = le32_to_cpu(tcon->fsDevInfo.DeviceType); | 211 | dev_type = le32_to_cpu(tcon->fsDevInfo.DeviceType); |
212 | length = | 212 | length = sprintf(buf, "\n%d) %s Uses: %d ", i, |
213 | sprintf(buf, | 213 | tcon->treeName, atomic_read(&tcon->useCount)); |
214 | "\n%d) %s Uses: %d Type: %s DevInfo: 0x%x " | 214 | buf += length; |
215 | "Attributes: 0x%x\nPathComponentMax: %d Status: %d", | 215 | if (tcon->nativeFileSystem) { |
216 | i, tcon->treeName, | 216 | length = sprintf(buf, "Type: %s ", |
217 | atomic_read(&tcon->useCount), | 217 | tcon->nativeFileSystem); |
218 | tcon->nativeFileSystem, | 218 | buf += length; |
219 | } | ||
220 | length = sprintf(buf, "DevInfo: 0x%x Attributes: 0x%x" | ||
221 | "\nPathComponentMax: %d Status: %d", | ||
219 | le32_to_cpu(tcon->fsDevInfo.DeviceCharacteristics), | 222 | le32_to_cpu(tcon->fsDevInfo.DeviceCharacteristics), |
220 | le32_to_cpu(tcon->fsAttrInfo.Attributes), | 223 | le32_to_cpu(tcon->fsAttrInfo.Attributes), |
221 | le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength), | 224 | le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength), |
@@ -876,11 +879,16 @@ security_flags_write(struct file *file, const char __user *buffer, | |||
876 | if (count < 3) { | 879 | if (count < 3) { |
877 | /* single char or single char followed by null */ | 880 | /* single char or single char followed by null */ |
878 | c = flags_string[0]; | 881 | c = flags_string[0]; |
879 | if (c == '0' || c == 'n' || c == 'N') | 882 | if (c == '0' || c == 'n' || c == 'N') { |
880 | extended_security = CIFSSEC_DEF; /* default */ | 883 | extended_security = CIFSSEC_DEF; /* default */ |
881 | else if (c == '1' || c == 'y' || c == 'Y') | 884 | return count; |
885 | } else if (c == '1' || c == 'y' || c == 'Y') { | ||
882 | extended_security = CIFSSEC_MAX; | 886 | extended_security = CIFSSEC_MAX; |
883 | return count; | 887 | return count; |
888 | } else if (!isdigit(c)) { | ||
889 | cERROR(1, ("invalid flag %c", c)); | ||
890 | return -EINVAL; | ||
891 | } | ||
884 | } | 892 | } |
885 | /* else we have a number */ | 893 | /* else we have a number */ |
886 | 894 | ||
diff --git a/fs/cifs/cifs_spnego.c b/fs/cifs/cifs_spnego.c new file mode 100644 index 000000000000..1529d2b12e9c --- /dev/null +++ b/fs/cifs/cifs_spnego.c | |||
@@ -0,0 +1,134 @@ | |||
1 | /* | ||
2 | * fs/cifs/cifs_spnego.c -- SPNEGO upcall management for CIFS | ||
3 | * | ||
4 | * Copyright (c) 2007 Red Hat, Inc. | ||
5 | * Author(s): Jeff Layton (jlayton@redhat.com) | ||
6 | * | ||
7 | * This library is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU Lesser General Public License as published | ||
9 | * by the Free Software Foundation; either version 2.1 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This library is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See | ||
15 | * the GNU Lesser General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU Lesser General Public License | ||
18 | * along with this library; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | |||
22 | #include <linux/list.h> | ||
23 | #include <linux/string.h> | ||
24 | #include <keys/user-type.h> | ||
25 | #include <linux/key-type.h> | ||
26 | #include "cifsglob.h" | ||
27 | #include "cifs_spnego.h" | ||
28 | #include "cifs_debug.h" | ||
29 | |||
30 | /* create a new cifs key */ | ||
31 | static int | ||
32 | cifs_spnego_key_instantiate(struct key *key, const void *data, size_t datalen) | ||
33 | { | ||
34 | char *payload; | ||
35 | int ret; | ||
36 | |||
37 | ret = -ENOMEM; | ||
38 | payload = kmalloc(datalen, GFP_KERNEL); | ||
39 | if (!payload) | ||
40 | goto error; | ||
41 | |||
42 | /* attach the data */ | ||
43 | memcpy(payload, data, datalen); | ||
44 | rcu_assign_pointer(key->payload.data, payload); | ||
45 | ret = 0; | ||
46 | |||
47 | error: | ||
48 | return ret; | ||
49 | } | ||
50 | |||
51 | static void | ||
52 | cifs_spnego_key_destroy(struct key *key) | ||
53 | { | ||
54 | kfree(key->payload.data); | ||
55 | } | ||
56 | |||
57 | |||
58 | /* | ||
59 | * keytype for CIFS spnego keys | ||
60 | */ | ||
61 | struct key_type cifs_spnego_key_type = { | ||
62 | .name = "cifs.spnego", | ||
63 | .instantiate = cifs_spnego_key_instantiate, | ||
64 | .match = user_match, | ||
65 | .destroy = cifs_spnego_key_destroy, | ||
66 | .describe = user_describe, | ||
67 | }; | ||
68 | |||
69 | #define MAX_VER_STR_LEN 9 /* length of longest version string e.g. | ||
70 | strlen(";ver=0xFF") */ | ||
71 | #define MAX_MECH_STR_LEN 13 /* length of longest security mechanism name, eg | ||
72 | in future could have strlen(";sec=ntlmsspi") */ | ||
73 | #define MAX_IPV6_ADDR_LEN 42 /* eg FEDC:BA98:7654:3210:FEDC:BA98:7654:3210/60 */ | ||
74 | /* get a key struct with a SPNEGO security blob, suitable for session setup */ | ||
75 | struct key * | ||
76 | cifs_get_spnego_key(struct cifsSesInfo *sesInfo) | ||
77 | { | ||
78 | struct TCP_Server_Info *server = sesInfo->server; | ||
79 | char *description, *dp; | ||
80 | size_t desc_len; | ||
81 | struct key *spnego_key; | ||
82 | const char *hostname = server->hostname; | ||
83 | |||
84 | /* BB: come up with better scheme for determining length */ | ||
85 | /* length of fields (with semicolons): ver=0xyz ipv4= ipaddress host= | ||
86 | hostname sec=mechanism uid=0x uid */ | ||
87 | desc_len = MAX_VER_STR_LEN + 5 + MAX_IPV6_ADDR_LEN + 1 + 6 + | ||
88 | strlen(hostname) + MAX_MECH_STR_LEN + 8 + (sizeof(uid_t) * 2); | ||
89 | spnego_key = ERR_PTR(-ENOMEM); | ||
90 | description = kzalloc(desc_len, GFP_KERNEL); | ||
91 | if (description == NULL) | ||
92 | goto out; | ||
93 | |||
94 | dp = description; | ||
95 | /* start with version and hostname portion of UNC string */ | ||
96 | spnego_key = ERR_PTR(-EINVAL); | ||
97 | sprintf(dp, "ver=0x%x;host=%s;", CIFS_SPNEGO_UPCALL_VERSION, | ||
98 | hostname); | ||
99 | dp = description + strlen(description); | ||
100 | |||
101 | /* add the server address */ | ||
102 | if (server->addr.sockAddr.sin_family == AF_INET) | ||
103 | sprintf(dp, "ip4=" NIPQUAD_FMT, | ||
104 | NIPQUAD(server->addr.sockAddr.sin_addr)); | ||
105 | else if (server->addr.sockAddr.sin_family == AF_INET6) | ||
106 | sprintf(dp, "ip6=" NIP6_SEQFMT, | ||
107 | NIP6(server->addr.sockAddr6.sin6_addr)); | ||
108 | else | ||
109 | goto out; | ||
110 | |||
111 | dp = description + strlen(description); | ||
112 | |||
113 | /* for now, only sec=krb5 is valid */ | ||
114 | if (server->secType == Kerberos) | ||
115 | sprintf(dp, ";sec=krb5"); | ||
116 | else | ||
117 | goto out; | ||
118 | |||
119 | dp = description + strlen(description); | ||
120 | sprintf(dp, ";uid=0x%x", sesInfo->linux_uid); | ||
121 | |||
122 | cFYI(1, ("key description = %s", description)); | ||
123 | spnego_key = request_key(&cifs_spnego_key_type, description, ""); | ||
124 | |||
125 | if (cifsFYI && !IS_ERR(spnego_key)) { | ||
126 | struct cifs_spnego_msg *msg = spnego_key->payload.data; | ||
127 | cifs_dump_mem("SPNEGO reply blob:", msg->data, | ||
128 | msg->secblob_len + msg->sesskey_len); | ||
129 | } | ||
130 | |||
131 | out: | ||
132 | kfree(description); | ||
133 | return spnego_key; | ||
134 | } | ||
diff --git a/fs/cifs/cifs_spnego.h b/fs/cifs/cifs_spnego.h new file mode 100644 index 000000000000..05a34b17a1ab --- /dev/null +++ b/fs/cifs/cifs_spnego.h | |||
@@ -0,0 +1,47 @@ | |||
1 | /* | ||
2 | * fs/cifs/cifs_spnego.h -- SPNEGO upcall management for CIFS | ||
3 | * | ||
4 | * Copyright (c) 2007 Red Hat, Inc. | ||
5 | * Author(s): Jeff Layton (jlayton@redhat.com) | ||
6 | * Steve French (sfrench@us.ibm.com) | ||
7 | * | ||
8 | * This library is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU Lesser General Public License as published | ||
10 | * by the Free Software Foundation; either version 2.1 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This library is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See | ||
16 | * the GNU Lesser General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU Lesser General Public License | ||
19 | * along with this library; if not, write to the Free Software | ||
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
21 | */ | ||
22 | |||
23 | #ifndef _CIFS_SPNEGO_H | ||
24 | #define _CIFS_SPNEGO_H | ||
25 | |||
26 | #define CIFS_SPNEGO_UPCALL_VERSION 1 | ||
27 | |||
28 | /* | ||
29 | * The version field should always be set to CIFS_SPNEGO_UPCALL_VERSION. | ||
30 | * The flags field is for future use. The request-key callout should set | ||
31 | * sesskey_len and secblob_len, and then concatenate the SessKey+SecBlob | ||
32 | * and stuff it in the data field. | ||
33 | */ | ||
34 | struct cifs_spnego_msg { | ||
35 | uint32_t version; | ||
36 | uint32_t flags; | ||
37 | uint32_t sesskey_len; | ||
38 | uint32_t secblob_len; | ||
39 | uint8_t data[1]; | ||
40 | }; | ||
41 | |||
42 | #ifdef __KERNEL__ | ||
43 | extern struct key_type cifs_spnego_key_type; | ||
44 | extern struct key *cifs_get_spnego_key(struct cifsSesInfo *sesInfo); | ||
45 | #endif /* KERNEL */ | ||
46 | |||
47 | #endif /* _CIFS_SPNEGO_H */ | ||
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c new file mode 100644 index 000000000000..c312adcba4fc --- /dev/null +++ b/fs/cifs/cifsacl.c | |||
@@ -0,0 +1,533 @@ | |||
1 | /* | ||
2 | * fs/cifs/cifsacl.c | ||
3 | * | ||
4 | * Copyright (C) International Business Machines Corp., 2007 | ||
5 | * Author(s): Steve French (sfrench@us.ibm.com) | ||
6 | * | ||
7 | * Contains the routines for mapping CIFS/NTFS ACLs | ||
8 | * | ||
9 | * This library is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU Lesser General Public License as published | ||
11 | * by the Free Software Foundation; either version 2.1 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This library is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See | ||
17 | * the GNU Lesser General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU Lesser General Public License | ||
20 | * along with this library; if not, write to the Free Software | ||
21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
22 | */ | ||
23 | |||
24 | #include <linux/fs.h> | ||
25 | #include "cifspdu.h" | ||
26 | #include "cifsglob.h" | ||
27 | #include "cifsacl.h" | ||
28 | #include "cifsproto.h" | ||
29 | #include "cifs_debug.h" | ||
30 | |||
31 | |||
32 | #ifdef CONFIG_CIFS_EXPERIMENTAL | ||
33 | |||
34 | static struct cifs_wksid wksidarr[NUM_WK_SIDS] = { | ||
35 | {{1, 0, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0} }, "null user"}, | ||
36 | {{1, 1, {0, 0, 0, 0, 0, 1}, {0, 0, 0, 0, 0} }, "nobody"}, | ||
37 | {{1, 1, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(11), 0, 0, 0, 0} }, "net-users"}, | ||
38 | {{1, 1, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(18), 0, 0, 0, 0} }, "sys"}, | ||
39 | {{1, 2, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(32), cpu_to_le32(544), 0, 0, 0} }, "root"}, | ||
40 | {{1, 2, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(32), cpu_to_le32(545), 0, 0, 0} }, "users"}, | ||
41 | {{1, 2, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(32), cpu_to_le32(546), 0, 0, 0} }, "guest"} } | ||
42 | ; | ||
43 | |||
44 | |||
45 | /* security id for everyone */ | ||
46 | static const struct cifs_sid sid_everyone = { | ||
47 | 1, 1, {0, 0, 0, 0, 0, 1}, {0} }; | ||
48 | /* group users */ | ||
49 | static const struct cifs_sid sid_user = | ||
50 | {1, 2 , {0, 0, 0, 0, 0, 5}, {} }; | ||
51 | |||
52 | |||
53 | int match_sid(struct cifs_sid *ctsid) | ||
54 | { | ||
55 | int i, j; | ||
56 | int num_subauth, num_sat, num_saw; | ||
57 | struct cifs_sid *cwsid; | ||
58 | |||
59 | if (!ctsid) | ||
60 | return (-1); | ||
61 | |||
62 | for (i = 0; i < NUM_WK_SIDS; ++i) { | ||
63 | cwsid = &(wksidarr[i].cifssid); | ||
64 | |||
65 | /* compare the revision */ | ||
66 | if (ctsid->revision != cwsid->revision) | ||
67 | continue; | ||
68 | |||
69 | /* compare all of the six auth values */ | ||
70 | for (j = 0; j < 6; ++j) { | ||
71 | if (ctsid->authority[j] != cwsid->authority[j]) | ||
72 | break; | ||
73 | } | ||
74 | if (j < 6) | ||
75 | continue; /* all of the auth values did not match */ | ||
76 | |||
77 | /* compare all of the subauth values if any */ | ||
78 | num_sat = ctsid->num_subauth; | ||
79 | num_saw = cwsid->num_subauth; | ||
80 | num_subauth = num_sat < num_saw ? num_sat : num_saw; | ||
81 | if (num_subauth) { | ||
82 | for (j = 0; j < num_subauth; ++j) { | ||
83 | if (ctsid->sub_auth[j] != cwsid->sub_auth[j]) | ||
84 | break; | ||
85 | } | ||
86 | if (j < num_subauth) | ||
87 | continue; /* all sub_auth values do not match */ | ||
88 | } | ||
89 | |||
90 | cFYI(1, ("matching sid: %s\n", wksidarr[i].sidname)); | ||
91 | return (0); /* sids compare/match */ | ||
92 | } | ||
93 | |||
94 | cFYI(1, ("No matching sid")); | ||
95 | return (-1); | ||
96 | } | ||
97 | |||
98 | /* if the two SIDs (roughly equivalent to a UUID for a user or group) are | ||
99 | the same returns 1, if they do not match returns 0 */ | ||
100 | int compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid) | ||
101 | { | ||
102 | int i; | ||
103 | int num_subauth, num_sat, num_saw; | ||
104 | |||
105 | if ((!ctsid) || (!cwsid)) | ||
106 | return (0); | ||
107 | |||
108 | /* compare the revision */ | ||
109 | if (ctsid->revision != cwsid->revision) | ||
110 | return (0); | ||
111 | |||
112 | /* compare all of the six auth values */ | ||
113 | for (i = 0; i < 6; ++i) { | ||
114 | if (ctsid->authority[i] != cwsid->authority[i]) | ||
115 | return (0); | ||
116 | } | ||
117 | |||
118 | /* compare all of the subauth values if any */ | ||
119 | num_sat = ctsid->num_subauth; | ||
120 | num_saw = cwsid->num_subauth; | ||
121 | num_subauth = num_sat < num_saw ? num_sat : num_saw; | ||
122 | if (num_subauth) { | ||
123 | for (i = 0; i < num_subauth; ++i) { | ||
124 | if (ctsid->sub_auth[i] != cwsid->sub_auth[i]) | ||
125 | return (0); | ||
126 | } | ||
127 | } | ||
128 | |||
129 | return (1); /* sids compare/match */ | ||
130 | } | ||
131 | |||
132 | /* | ||
133 | change posix mode to reflect permissions | ||
134 | pmode is the existing mode (we only want to overwrite part of this | ||
135 | bits to set can be: S_IRWXU, S_IRWXG or S_IRWXO ie 00700 or 00070 or 00007 | ||
136 | */ | ||
137 | static void access_flags_to_mode(__le32 ace_flags, int type, umode_t *pmode, | ||
138 | umode_t *pbits_to_set) | ||
139 | { | ||
140 | __u32 flags = le32_to_cpu(ace_flags); | ||
141 | /* the order of ACEs is important. The canonical order is to begin with | ||
142 | DENY entries followed by ALLOW, otherwise an allow entry could be | ||
143 | encountered first, making the subsequent deny entry like "dead code" | ||
144 | which would be superflous since Windows stops when a match is made | ||
145 | for the operation you are trying to perform for your user */ | ||
146 | |||
147 | /* For deny ACEs we change the mask so that subsequent allow access | ||
148 | control entries do not turn on the bits we are denying */ | ||
149 | if (type == ACCESS_DENIED) { | ||
150 | if (flags & GENERIC_ALL) { | ||
151 | *pbits_to_set &= ~S_IRWXUGO; | ||
152 | } | ||
153 | if ((flags & GENERIC_WRITE) || | ||
154 | ((flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS)) | ||
155 | *pbits_to_set &= ~S_IWUGO; | ||
156 | if ((flags & GENERIC_READ) || | ||
157 | ((flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS)) | ||
158 | *pbits_to_set &= ~S_IRUGO; | ||
159 | if ((flags & GENERIC_EXECUTE) || | ||
160 | ((flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS)) | ||
161 | *pbits_to_set &= ~S_IXUGO; | ||
162 | return; | ||
163 | } else if (type != ACCESS_ALLOWED) { | ||
164 | cERROR(1, ("unknown access control type %d", type)); | ||
165 | return; | ||
166 | } | ||
167 | /* else ACCESS_ALLOWED type */ | ||
168 | |||
169 | if (flags & GENERIC_ALL) { | ||
170 | *pmode |= (S_IRWXUGO & (*pbits_to_set)); | ||
171 | #ifdef CONFIG_CIFS_DEBUG2 | ||
172 | cFYI(1, ("all perms")); | ||
173 | #endif | ||
174 | return; | ||
175 | } | ||
176 | if ((flags & GENERIC_WRITE) || | ||
177 | ((flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS)) | ||
178 | *pmode |= (S_IWUGO & (*pbits_to_set)); | ||
179 | if ((flags & GENERIC_READ) || | ||
180 | ((flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS)) | ||
181 | *pmode |= (S_IRUGO & (*pbits_to_set)); | ||
182 | if ((flags & GENERIC_EXECUTE) || | ||
183 | ((flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS)) | ||
184 | *pmode |= (S_IXUGO & (*pbits_to_set)); | ||
185 | |||
186 | #ifdef CONFIG_CIFS_DEBUG2 | ||
187 | cFYI(1, ("access flags 0x%x mode now 0x%x", flags, *pmode)); | ||
188 | #endif | ||
189 | return; | ||
190 | } | ||
191 | |||
192 | /* | ||
193 | Generate access flags to reflect permissions mode is the existing mode. | ||
194 | This function is called for every ACE in the DACL whose SID matches | ||
195 | with either owner or group or everyone. | ||
196 | */ | ||
197 | |||
198 | static void mode_to_access_flags(umode_t mode, umode_t bits_to_use, | ||
199 | __u32 *pace_flags) | ||
200 | { | ||
201 | /* reset access mask */ | ||
202 | *pace_flags = 0x0; | ||
203 | |||
204 | /* bits to use are either S_IRWXU or S_IRWXG or S_IRWXO */ | ||
205 | mode &= bits_to_use; | ||
206 | |||
207 | /* check for R/W/X UGO since we do not know whose flags | ||
208 | is this but we have cleared all the bits sans RWX for | ||
209 | either user or group or other as per bits_to_use */ | ||
210 | if (mode & S_IRUGO) | ||
211 | *pace_flags |= SET_FILE_READ_RIGHTS; | ||
212 | if (mode & S_IWUGO) | ||
213 | *pace_flags |= SET_FILE_WRITE_RIGHTS; | ||
214 | if (mode & S_IXUGO) | ||
215 | *pace_flags |= SET_FILE_EXEC_RIGHTS; | ||
216 | |||
217 | #ifdef CONFIG_CIFS_DEBUG2 | ||
218 | cFYI(1, ("mode: 0x%x, access flags now 0x%x", mode, *pace_flags)); | ||
219 | #endif | ||
220 | return; | ||
221 | } | ||
222 | |||
223 | |||
224 | #ifdef CONFIG_CIFS_DEBUG2 | ||
225 | static void dump_ace(struct cifs_ace *pace, char *end_of_acl) | ||
226 | { | ||
227 | int num_subauth; | ||
228 | |||
229 | /* validate that we do not go past end of acl */ | ||
230 | |||
231 | if (le16_to_cpu(pace->size) < 16) { | ||
232 | cERROR(1, ("ACE too small, %d", le16_to_cpu(pace->size))); | ||
233 | return; | ||
234 | } | ||
235 | |||
236 | if (end_of_acl < (char *)pace + le16_to_cpu(pace->size)) { | ||
237 | cERROR(1, ("ACL too small to parse ACE")); | ||
238 | return; | ||
239 | } | ||
240 | |||
241 | num_subauth = pace->sid.num_subauth; | ||
242 | if (num_subauth) { | ||
243 | int i; | ||
244 | cFYI(1, ("ACE revision %d num_auth %d type %d flags %d size %d", | ||
245 | pace->sid.revision, pace->sid.num_subauth, pace->type, | ||
246 | pace->flags, pace->size)); | ||
247 | for (i = 0; i < num_subauth; ++i) { | ||
248 | cFYI(1, ("ACE sub_auth[%d]: 0x%x", i, | ||
249 | le32_to_cpu(pace->sid.sub_auth[i]))); | ||
250 | } | ||
251 | |||
252 | /* BB add length check to make sure that we do not have huge | ||
253 | num auths and therefore go off the end */ | ||
254 | } | ||
255 | |||
256 | return; | ||
257 | } | ||
258 | #endif | ||
259 | |||
260 | |||
261 | static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl, | ||
262 | struct cifs_sid *pownersid, struct cifs_sid *pgrpsid, | ||
263 | struct inode *inode) | ||
264 | { | ||
265 | int i; | ||
266 | int num_aces = 0; | ||
267 | int acl_size; | ||
268 | char *acl_base; | ||
269 | struct cifs_ace **ppace; | ||
270 | |||
271 | /* BB need to add parm so we can store the SID BB */ | ||
272 | |||
273 | if (!pdacl) { | ||
274 | /* no DACL in the security descriptor, set | ||
275 | all the permissions for user/group/other */ | ||
276 | inode->i_mode |= S_IRWXUGO; | ||
277 | return; | ||
278 | } | ||
279 | |||
280 | /* validate that we do not go past end of acl */ | ||
281 | if (end_of_acl < (char *)pdacl + le16_to_cpu(pdacl->size)) { | ||
282 | cERROR(1, ("ACL too small to parse DACL")); | ||
283 | return; | ||
284 | } | ||
285 | |||
286 | #ifdef CONFIG_CIFS_DEBUG2 | ||
287 | cFYI(1, ("DACL revision %d size %d num aces %d", | ||
288 | le16_to_cpu(pdacl->revision), le16_to_cpu(pdacl->size), | ||
289 | le32_to_cpu(pdacl->num_aces))); | ||
290 | #endif | ||
291 | |||
292 | /* reset rwx permissions for user/group/other. | ||
293 | Also, if num_aces is 0 i.e. DACL has no ACEs, | ||
294 | user/group/other have no permissions */ | ||
295 | inode->i_mode &= ~(S_IRWXUGO); | ||
296 | |||
297 | acl_base = (char *)pdacl; | ||
298 | acl_size = sizeof(struct cifs_acl); | ||
299 | |||
300 | num_aces = le32_to_cpu(pdacl->num_aces); | ||
301 | if (num_aces > 0) { | ||
302 | umode_t user_mask = S_IRWXU; | ||
303 | umode_t group_mask = S_IRWXG; | ||
304 | umode_t other_mask = S_IRWXO; | ||
305 | |||
306 | ppace = kmalloc(num_aces * sizeof(struct cifs_ace *), | ||
307 | GFP_KERNEL); | ||
308 | |||
309 | /* cifscred->cecount = pdacl->num_aces; | ||
310 | cifscred->aces = kmalloc(num_aces * | ||
311 | sizeof(struct cifs_ace *), GFP_KERNEL);*/ | ||
312 | |||
313 | for (i = 0; i < num_aces; ++i) { | ||
314 | ppace[i] = (struct cifs_ace *) (acl_base + acl_size); | ||
315 | #ifdef CONFIG_CIFS_DEBUG2 | ||
316 | dump_ace(ppace[i], end_of_acl); | ||
317 | #endif | ||
318 | if (compare_sids(&(ppace[i]->sid), pownersid)) | ||
319 | access_flags_to_mode(ppace[i]->access_req, | ||
320 | ppace[i]->type, | ||
321 | &(inode->i_mode), | ||
322 | &user_mask); | ||
323 | if (compare_sids(&(ppace[i]->sid), pgrpsid)) | ||
324 | access_flags_to_mode(ppace[i]->access_req, | ||
325 | ppace[i]->type, | ||
326 | &(inode->i_mode), | ||
327 | &group_mask); | ||
328 | if (compare_sids(&(ppace[i]->sid), &sid_everyone)) | ||
329 | access_flags_to_mode(ppace[i]->access_req, | ||
330 | ppace[i]->type, | ||
331 | &(inode->i_mode), | ||
332 | &other_mask); | ||
333 | |||
334 | /* memcpy((void *)(&(cifscred->aces[i])), | ||
335 | (void *)ppace[i], | ||
336 | sizeof(struct cifs_ace)); */ | ||
337 | |||
338 | acl_base = (char *)ppace[i]; | ||
339 | acl_size = le16_to_cpu(ppace[i]->size); | ||
340 | } | ||
341 | |||
342 | kfree(ppace); | ||
343 | } | ||
344 | |||
345 | return; | ||
346 | } | ||
347 | |||
348 | |||
349 | static int parse_sid(struct cifs_sid *psid, char *end_of_acl) | ||
350 | { | ||
351 | /* BB need to add parm so we can store the SID BB */ | ||
352 | |||
353 | /* validate that we do not go past end of ACL - sid must be at least 8 | ||
354 | bytes long (assuming no sub-auths - e.g. the null SID */ | ||
355 | if (end_of_acl < (char *)psid + 8) { | ||
356 | cERROR(1, ("ACL too small to parse SID %p", psid)); | ||
357 | return -EINVAL; | ||
358 | } | ||
359 | |||
360 | if (psid->num_subauth) { | ||
361 | #ifdef CONFIG_CIFS_DEBUG2 | ||
362 | int i; | ||
363 | cFYI(1, ("SID revision %d num_auth %d", | ||
364 | psid->revision, psid->num_subauth)); | ||
365 | |||
366 | for (i = 0; i < psid->num_subauth; i++) { | ||
367 | cFYI(1, ("SID sub_auth[%d]: 0x%x ", i, | ||
368 | le32_to_cpu(psid->sub_auth[i]))); | ||
369 | } | ||
370 | |||
371 | /* BB add length check to make sure that we do not have huge | ||
372 | num auths and therefore go off the end */ | ||
373 | cFYI(1, ("RID 0x%x", | ||
374 | le32_to_cpu(psid->sub_auth[psid->num_subauth-1]))); | ||
375 | #endif | ||
376 | } | ||
377 | |||
378 | return 0; | ||
379 | } | ||
380 | |||
381 | |||
382 | /* Convert CIFS ACL to POSIX form */ | ||
383 | static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len, | ||
384 | struct inode *inode) | ||
385 | { | ||
386 | int rc; | ||
387 | struct cifs_sid *owner_sid_ptr, *group_sid_ptr; | ||
388 | struct cifs_acl *dacl_ptr; /* no need for SACL ptr */ | ||
389 | char *end_of_acl = ((char *)pntsd) + acl_len; | ||
390 | __u32 dacloffset; | ||
391 | |||
392 | if ((inode == NULL) || (pntsd == NULL)) | ||
393 | return -EIO; | ||
394 | |||
395 | owner_sid_ptr = (struct cifs_sid *)((char *)pntsd + | ||
396 | le32_to_cpu(pntsd->osidoffset)); | ||
397 | group_sid_ptr = (struct cifs_sid *)((char *)pntsd + | ||
398 | le32_to_cpu(pntsd->gsidoffset)); | ||
399 | dacloffset = le32_to_cpu(pntsd->dacloffset); | ||
400 | dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset); | ||
401 | #ifdef CONFIG_CIFS_DEBUG2 | ||
402 | cFYI(1, ("revision %d type 0x%x ooffset 0x%x goffset 0x%x " | ||
403 | "sacloffset 0x%x dacloffset 0x%x", | ||
404 | pntsd->revision, pntsd->type, le32_to_cpu(pntsd->osidoffset), | ||
405 | le32_to_cpu(pntsd->gsidoffset), | ||
406 | le32_to_cpu(pntsd->sacloffset), dacloffset)); | ||
407 | #endif | ||
408 | /* cifs_dump_mem("owner_sid: ", owner_sid_ptr, 64); */ | ||
409 | rc = parse_sid(owner_sid_ptr, end_of_acl); | ||
410 | if (rc) | ||
411 | return rc; | ||
412 | |||
413 | rc = parse_sid(group_sid_ptr, end_of_acl); | ||
414 | if (rc) | ||
415 | return rc; | ||
416 | |||
417 | if (dacloffset) | ||
418 | parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr, | ||
419 | group_sid_ptr, inode); | ||
420 | else | ||
421 | cFYI(1, ("no ACL")); /* BB grant all or default perms? */ | ||
422 | |||
423 | /* cifscred->uid = owner_sid_ptr->rid; | ||
424 | cifscred->gid = group_sid_ptr->rid; | ||
425 | memcpy((void *)(&(cifscred->osid)), (void *)owner_sid_ptr, | ||
426 | sizeof(struct cifs_sid)); | ||
427 | memcpy((void *)(&(cifscred->gsid)), (void *)group_sid_ptr, | ||
428 | sizeof(struct cifs_sid)); */ | ||
429 | |||
430 | |||
431 | return (0); | ||
432 | } | ||
433 | |||
434 | |||
435 | /* Retrieve an ACL from the server */ | ||
436 | static struct cifs_ntsd *get_cifs_acl(u32 *pacllen, struct inode *inode, | ||
437 | const char *path) | ||
438 | { | ||
439 | struct cifsFileInfo *open_file; | ||
440 | int unlock_file = FALSE; | ||
441 | int xid; | ||
442 | int rc = -EIO; | ||
443 | __u16 fid; | ||
444 | struct super_block *sb; | ||
445 | struct cifs_sb_info *cifs_sb; | ||
446 | struct cifs_ntsd *pntsd = NULL; | ||
447 | |||
448 | cFYI(1, ("get mode from ACL for %s", path)); | ||
449 | |||
450 | if (inode == NULL) | ||
451 | return NULL; | ||
452 | |||
453 | xid = GetXid(); | ||
454 | open_file = find_readable_file(CIFS_I(inode)); | ||
455 | sb = inode->i_sb; | ||
456 | if (sb == NULL) { | ||
457 | FreeXid(xid); | ||
458 | return NULL; | ||
459 | } | ||
460 | cifs_sb = CIFS_SB(sb); | ||
461 | |||
462 | if (open_file) { | ||
463 | unlock_file = TRUE; | ||
464 | fid = open_file->netfid; | ||
465 | } else { | ||
466 | int oplock = FALSE; | ||
467 | /* open file */ | ||
468 | rc = CIFSSMBOpen(xid, cifs_sb->tcon, path, FILE_OPEN, | ||
469 | READ_CONTROL, 0, &fid, &oplock, NULL, | ||
470 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & | ||
471 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
472 | if (rc != 0) { | ||
473 | cERROR(1, ("Unable to open file to get ACL")); | ||
474 | FreeXid(xid); | ||
475 | return NULL; | ||
476 | } | ||
477 | } | ||
478 | |||
479 | rc = CIFSSMBGetCIFSACL(xid, cifs_sb->tcon, fid, &pntsd, pacllen); | ||
480 | cFYI(1, ("GetCIFSACL rc = %d ACL len %d", rc, *pacllen)); | ||
481 | if (unlock_file == TRUE) | ||
482 | atomic_dec(&open_file->wrtPending); | ||
483 | else | ||
484 | CIFSSMBClose(xid, cifs_sb->tcon, fid); | ||
485 | |||
486 | FreeXid(xid); | ||
487 | return pntsd; | ||
488 | } | ||
489 | |||
490 | /* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */ | ||
491 | void acl_to_uid_mode(struct inode *inode, const char *path) | ||
492 | { | ||
493 | struct cifs_ntsd *pntsd = NULL; | ||
494 | u32 acllen = 0; | ||
495 | int rc = 0; | ||
496 | |||
497 | #ifdef CONFIG_CIFS_DEBUG2 | ||
498 | cFYI(1, ("converting ACL to mode for %s", path)); | ||
499 | #endif | ||
500 | pntsd = get_cifs_acl(&acllen, inode, path); | ||
501 | |||
502 | /* if we can retrieve the ACL, now parse Access Control Entries, ACEs */ | ||
503 | if (pntsd) | ||
504 | rc = parse_sec_desc(pntsd, acllen, inode); | ||
505 | if (rc) | ||
506 | cFYI(1, ("parse sec desc failed rc = %d", rc)); | ||
507 | |||
508 | kfree(pntsd); | ||
509 | return; | ||
510 | } | ||
511 | |||
512 | /* Convert mode bits to an ACL so we can update the ACL on the server */ | ||
513 | int mode_to_acl(struct inode *inode, const char *path) | ||
514 | { | ||
515 | int rc = 0; | ||
516 | __u32 acllen = 0; | ||
517 | struct cifs_ntsd *pntsd = NULL; | ||
518 | |||
519 | cFYI(1, ("set ACL from mode for %s", path)); | ||
520 | |||
521 | /* Get the security descriptor */ | ||
522 | pntsd = get_cifs_acl(&acllen, inode, path); | ||
523 | |||
524 | /* Add/Modify the three ACEs for owner, group, everyone | ||
525 | while retaining the other ACEs */ | ||
526 | |||
527 | /* Set the security descriptor */ | ||
528 | |||
529 | |||
530 | kfree(pntsd); | ||
531 | return rc; | ||
532 | } | ||
533 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ | ||
diff --git a/fs/cifs/cifsacl.h b/fs/cifs/cifsacl.h index 5eff35d6e564..93a7c3462ea2 100644 --- a/fs/cifs/cifsacl.h +++ b/fs/cifs/cifsacl.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * fs/cifs/cifsacl.h | 2 | * fs/cifs/cifsacl.h |
3 | * | 3 | * |
4 | * Copyright (c) International Business Machines Corp., 2005 | 4 | * Copyright (c) International Business Machines Corp., 2007 |
5 | * Author(s): Steve French (sfrench@us.ibm.com) | 5 | * Author(s): Steve French (sfrench@us.ibm.com) |
6 | * | 6 | * |
7 | * This library is free software; you can redistribute it and/or modify | 7 | * This library is free software; you can redistribute it and/or modify |
@@ -22,17 +22,62 @@ | |||
22 | #ifndef _CIFSACL_H | 22 | #ifndef _CIFSACL_H |
23 | #define _CIFSACL_H | 23 | #define _CIFSACL_H |
24 | 24 | ||
25 | |||
26 | #define NUM_AUTHS 6 /* number of authority fields */ | ||
27 | #define NUM_SUBAUTHS 5 /* number of sub authority fields */ | ||
28 | #define NUM_WK_SIDS 7 /* number of well known sids */ | ||
29 | #define SIDNAMELENGTH 20 /* long enough for the ones we care about */ | ||
30 | |||
31 | #define READ_BIT 0x4 | ||
32 | #define WRITE_BIT 0x2 | ||
33 | #define EXEC_BIT 0x1 | ||
34 | |||
35 | #define UBITSHIFT 6 | ||
36 | #define GBITSHIFT 3 | ||
37 | |||
38 | #define ACCESS_ALLOWED 0 | ||
39 | #define ACCESS_DENIED 1 | ||
40 | |||
41 | struct cifs_ntsd { | ||
42 | __le16 revision; /* revision level */ | ||
43 | __le16 type; | ||
44 | __le32 osidoffset; | ||
45 | __le32 gsidoffset; | ||
46 | __le32 sacloffset; | ||
47 | __le32 dacloffset; | ||
48 | } __attribute__((packed)); | ||
49 | |||
25 | struct cifs_sid { | 50 | struct cifs_sid { |
26 | __u8 revision; /* revision level */ | 51 | __u8 revision; /* revision level */ |
27 | __u8 num_subauths; | 52 | __u8 num_subauth; |
28 | __u8 authority[6]; | 53 | __u8 authority[6]; |
29 | __u32 sub_auth[4]; | 54 | __le32 sub_auth[5]; /* sub_auth[num_subauth] */ |
30 | /* next sub_auth if any ... */ | ||
31 | } __attribute__((packed)); | 55 | } __attribute__((packed)); |
32 | 56 | ||
33 | /* everyone */ | 57 | struct cifs_acl { |
34 | /* extern const struct cifs_sid sid_everyone;*/ | 58 | __le16 revision; /* revision level */ |
35 | /* group users */ | 59 | __le16 size; |
36 | /* extern const struct cifs_sid sid_user;*/ | 60 | __le32 num_aces; |
61 | } __attribute__((packed)); | ||
62 | |||
63 | struct cifs_ace { | ||
64 | __u8 type; | ||
65 | __u8 flags; | ||
66 | __le16 size; | ||
67 | __le32 access_req; | ||
68 | struct cifs_sid sid; /* ie UUID of user or group who gets these perms */ | ||
69 | } __attribute__((packed)); | ||
70 | |||
71 | struct cifs_wksid { | ||
72 | struct cifs_sid cifssid; | ||
73 | char sidname[SIDNAMELENGTH]; | ||
74 | } __attribute__((packed)); | ||
75 | |||
76 | #ifdef CONFIG_CIFS_EXPERIMENTAL | ||
77 | |||
78 | extern int match_sid(struct cifs_sid *); | ||
79 | extern int compare_sids(const struct cifs_sid *, const struct cifs_sid *); | ||
80 | |||
81 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ | ||
37 | 82 | ||
38 | #endif /* _CIFSACL_H */ | 83 | #endif /* _CIFSACL_H */ |
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c index 36272293027d..4ff8939c6cc7 100644 --- a/fs/cifs/cifsencrypt.c +++ b/fs/cifs/cifsencrypt.c | |||
@@ -99,15 +99,16 @@ static int cifs_calc_signature2(const struct kvec *iov, int n_vec, | |||
99 | MD5Init(&context); | 99 | MD5Init(&context); |
100 | MD5Update(&context, (char *)&key->data, key->len); | 100 | MD5Update(&context, (char *)&key->data, key->len); |
101 | for (i = 0; i < n_vec; i++) { | 101 | for (i = 0; i < n_vec; i++) { |
102 | if (iov[i].iov_len == 0) | ||
103 | continue; | ||
102 | if (iov[i].iov_base == NULL) { | 104 | if (iov[i].iov_base == NULL) { |
103 | cERROR(1, ("null iovec entry")); | 105 | cERROR(1, ("null iovec entry")); |
104 | return -EIO; | 106 | return -EIO; |
105 | } else if (iov[i].iov_len == 0) | 107 | } |
106 | break; /* bail out if we are sent nothing to sign */ | ||
107 | /* The first entry includes a length field (which does not get | 108 | /* The first entry includes a length field (which does not get |
108 | signed that occupies the first 4 bytes before the header */ | 109 | signed that occupies the first 4 bytes before the header */ |
109 | if (i == 0) { | 110 | if (i == 0) { |
110 | if (iov[0].iov_len <= 8 ) /* cmd field at offset 9 */ | 111 | if (iov[0].iov_len <= 8) /* cmd field at offset 9 */ |
111 | break; /* nothing to sign or corrupt header */ | 112 | break; /* nothing to sign or corrupt header */ |
112 | MD5Update(&context, iov[0].iov_base+4, | 113 | MD5Update(&context, iov[0].iov_base+4, |
113 | iov[0].iov_len-4); | 114 | iov[0].iov_len-4); |
@@ -122,7 +123,7 @@ static int cifs_calc_signature2(const struct kvec *iov, int n_vec, | |||
122 | 123 | ||
123 | 124 | ||
124 | int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server, | 125 | int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server, |
125 | __u32 * pexpected_response_sequence_number) | 126 | __u32 *pexpected_response_sequence_number) |
126 | { | 127 | { |
127 | int rc = 0; | 128 | int rc = 0; |
128 | char smb_signature[20]; | 129 | char smb_signature[20]; |
@@ -345,7 +346,7 @@ static int calc_ntlmv2_hash(struct cifsSesInfo *ses, | |||
345 | user = kmalloc(2 + (len * 2), GFP_KERNEL); | 346 | user = kmalloc(2 + (len * 2), GFP_KERNEL); |
346 | if (user == NULL) | 347 | if (user == NULL) |
347 | goto calc_exit_2; | 348 | goto calc_exit_2; |
348 | len = cifs_strtoUCS(user, ses->userName, len, nls_cp); | 349 | len = cifs_strtoUCS((__le16 *)user, ses->userName, len, nls_cp); |
349 | UniStrupr(user); | 350 | UniStrupr(user); |
350 | hmac_md5_update((char *)user, 2*len, pctxt); | 351 | hmac_md5_update((char *)user, 2*len, pctxt); |
351 | 352 | ||
@@ -356,7 +357,8 @@ static int calc_ntlmv2_hash(struct cifsSesInfo *ses, | |||
356 | domain = kmalloc(2 + (len * 2), GFP_KERNEL); | 357 | domain = kmalloc(2 + (len * 2), GFP_KERNEL); |
357 | if (domain == NULL) | 358 | if (domain == NULL) |
358 | goto calc_exit_1; | 359 | goto calc_exit_1; |
359 | len = cifs_strtoUCS(domain, ses->domainName, len, nls_cp); | 360 | len = cifs_strtoUCS((__le16 *)domain, ses->domainName, len, |
361 | nls_cp); | ||
360 | /* the following line was removed since it didn't work well | 362 | /* the following line was removed since it didn't work well |
361 | with lower cased domain name that passed as an option. | 363 | with lower cased domain name that passed as an option. |
362 | Maybe converting the domain name earlier makes sense */ | 364 | Maybe converting the domain name earlier makes sense */ |
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index ba8f7868cb23..093beaa3900d 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
@@ -43,16 +43,14 @@ | |||
43 | #include "cifs_debug.h" | 43 | #include "cifs_debug.h" |
44 | #include "cifs_fs_sb.h" | 44 | #include "cifs_fs_sb.h" |
45 | #include <linux/mm.h> | 45 | #include <linux/mm.h> |
46 | #include <linux/key-type.h> | ||
47 | #include "cifs_spnego.h" | ||
46 | #define CIFS_MAGIC_NUMBER 0xFF534D42 /* the first four bytes of SMB PDUs */ | 48 | #define CIFS_MAGIC_NUMBER 0xFF534D42 /* the first four bytes of SMB PDUs */ |
47 | 49 | ||
48 | #ifdef CONFIG_CIFS_QUOTA | 50 | #ifdef CONFIG_CIFS_QUOTA |
49 | static struct quotactl_ops cifs_quotactl_ops; | 51 | static struct quotactl_ops cifs_quotactl_ops; |
50 | #endif /* QUOTA */ | 52 | #endif /* QUOTA */ |
51 | 53 | ||
52 | #ifdef CONFIG_CIFS_EXPERIMENTAL | ||
53 | extern struct export_operations cifs_export_ops; | ||
54 | #endif /* EXPERIMENTAL */ | ||
55 | |||
56 | int cifsFYI = 0; | 54 | int cifsFYI = 0; |
57 | int cifsERROR = 1; | 55 | int cifsERROR = 1; |
58 | int traceSMB = 0; | 56 | int traceSMB = 0; |
@@ -240,9 +238,9 @@ static int cifs_permission(struct inode *inode, int mask, struct nameidata *nd) | |||
240 | 238 | ||
241 | cifs_sb = CIFS_SB(inode->i_sb); | 239 | cifs_sb = CIFS_SB(inode->i_sb); |
242 | 240 | ||
243 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) { | 241 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) |
244 | return 0; | 242 | return 0; |
245 | } else /* file mode might have been restricted at mount time | 243 | else /* file mode might have been restricted at mount time |
246 | on the client (above and beyond ACL on servers) for | 244 | on the client (above and beyond ACL on servers) for |
247 | servers which do not support setting and viewing mode bits, | 245 | servers which do not support setting and viewing mode bits, |
248 | so allowing client to check permissions is useful */ | 246 | so allowing client to check permissions is useful */ |
@@ -268,6 +266,7 @@ cifs_alloc_inode(struct super_block *sb) | |||
268 | cifs_inode->cifsAttrs = 0x20; /* default */ | 266 | cifs_inode->cifsAttrs = 0x20; /* default */ |
269 | atomic_set(&cifs_inode->inUse, 0); | 267 | atomic_set(&cifs_inode->inUse, 0); |
270 | cifs_inode->time = 0; | 268 | cifs_inode->time = 0; |
269 | cifs_inode->write_behind_rc = 0; | ||
271 | /* Until the file is open and we have gotten oplock | 270 | /* Until the file is open and we have gotten oplock |
272 | info back from the server, can not assume caching of | 271 | info back from the server, can not assume caching of |
273 | file data or metadata */ | 272 | file data or metadata */ |
@@ -312,15 +311,15 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m) | |||
312 | seq_printf(s, ",domain=%s", | 311 | seq_printf(s, ",domain=%s", |
313 | cifs_sb->tcon->ses->domainName); | 312 | cifs_sb->tcon->ses->domainName); |
314 | } | 313 | } |
314 | if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) || | ||
315 | !(cifs_sb->tcon->unix_ext)) | ||
316 | seq_printf(s, ",uid=%d", cifs_sb->mnt_uid); | ||
317 | if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) || | ||
318 | !(cifs_sb->tcon->unix_ext)) | ||
319 | seq_printf(s, ",gid=%d", cifs_sb->mnt_gid); | ||
315 | } | 320 | } |
316 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) | 321 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) |
317 | seq_printf(s, ",posixpaths"); | 322 | seq_printf(s, ",posixpaths"); |
318 | if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) || | ||
319 | !(cifs_sb->tcon->unix_ext)) | ||
320 | seq_printf(s, ",uid=%d", cifs_sb->mnt_uid); | ||
321 | if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) || | ||
322 | !(cifs_sb->tcon->unix_ext)) | ||
323 | seq_printf(s, ",gid=%d", cifs_sb->mnt_gid); | ||
324 | seq_printf(s, ",rsize=%d", cifs_sb->rsize); | 323 | seq_printf(s, ",rsize=%d", cifs_sb->rsize); |
325 | seq_printf(s, ",wsize=%d", cifs_sb->wsize); | 324 | seq_printf(s, ",wsize=%d", cifs_sb->wsize); |
326 | } | 325 | } |
@@ -346,7 +345,7 @@ int cifs_xquota_set(struct super_block *sb, int quota_type, qid_t qid, | |||
346 | if (pTcon) { | 345 | if (pTcon) { |
347 | cFYI(1, ("set type: 0x%x id: %d", quota_type, qid)); | 346 | cFYI(1, ("set type: 0x%x id: %d", quota_type, qid)); |
348 | } else { | 347 | } else { |
349 | return -EIO; | 348 | rc = -EIO; |
350 | } | 349 | } |
351 | 350 | ||
352 | FreeXid(xid); | 351 | FreeXid(xid); |
@@ -716,7 +715,7 @@ static int | |||
716 | cifs_init_inodecache(void) | 715 | cifs_init_inodecache(void) |
717 | { | 716 | { |
718 | cifs_inode_cachep = kmem_cache_create("cifs_inode_cache", | 717 | cifs_inode_cachep = kmem_cache_create("cifs_inode_cache", |
719 | sizeof (struct cifsInodeInfo), | 718 | sizeof(struct cifsInodeInfo), |
720 | 0, (SLAB_RECLAIM_ACCOUNT| | 719 | 0, (SLAB_RECLAIM_ACCOUNT| |
721 | SLAB_MEM_SPREAD), | 720 | SLAB_MEM_SPREAD), |
722 | cifs_init_once); | 721 | cifs_init_once); |
@@ -816,8 +815,8 @@ static int | |||
816 | cifs_init_mids(void) | 815 | cifs_init_mids(void) |
817 | { | 816 | { |
818 | cifs_mid_cachep = kmem_cache_create("cifs_mpx_ids", | 817 | cifs_mid_cachep = kmem_cache_create("cifs_mpx_ids", |
819 | sizeof (struct mid_q_entry), 0, | 818 | sizeof(struct mid_q_entry), 0, |
820 | SLAB_HWCACHE_ALIGN, NULL); | 819 | SLAB_HWCACHE_ALIGN, NULL); |
821 | if (cifs_mid_cachep == NULL) | 820 | if (cifs_mid_cachep == NULL) |
822 | return -ENOMEM; | 821 | return -ENOMEM; |
823 | 822 | ||
@@ -829,8 +828,8 @@ cifs_init_mids(void) | |||
829 | } | 828 | } |
830 | 829 | ||
831 | cifs_oplock_cachep = kmem_cache_create("cifs_oplock_structs", | 830 | cifs_oplock_cachep = kmem_cache_create("cifs_oplock_structs", |
832 | sizeof (struct oplock_q_entry), 0, | 831 | sizeof(struct oplock_q_entry), 0, |
833 | SLAB_HWCACHE_ALIGN, NULL); | 832 | SLAB_HWCACHE_ALIGN, NULL); |
834 | if (cifs_oplock_cachep == NULL) { | 833 | if (cifs_oplock_cachep == NULL) { |
835 | mempool_destroy(cifs_mid_poolp); | 834 | mempool_destroy(cifs_mid_poolp); |
836 | kmem_cache_destroy(cifs_mid_cachep); | 835 | kmem_cache_destroy(cifs_mid_cachep); |
@@ -854,7 +853,7 @@ static int cifs_oplock_thread(void *dummyarg) | |||
854 | struct cifsTconInfo *pTcon; | 853 | struct cifsTconInfo *pTcon; |
855 | struct inode *inode; | 854 | struct inode *inode; |
856 | __u16 netfid; | 855 | __u16 netfid; |
857 | int rc; | 856 | int rc, waitrc = 0; |
858 | 857 | ||
859 | set_freezable(); | 858 | set_freezable(); |
860 | do { | 859 | do { |
@@ -882,12 +881,15 @@ static int cifs_oplock_thread(void *dummyarg) | |||
882 | the call */ | 881 | the call */ |
883 | /* mutex_lock(&inode->i_mutex);*/ | 882 | /* mutex_lock(&inode->i_mutex);*/ |
884 | if (S_ISREG(inode->i_mode)) { | 883 | if (S_ISREG(inode->i_mode)) { |
885 | rc = filemap_fdatawrite(inode->i_mapping); | 884 | rc = |
885 | filemap_fdatawrite(inode->i_mapping); | ||
886 | if (CIFS_I(inode)->clientCanCacheRead | 886 | if (CIFS_I(inode)->clientCanCacheRead |
887 | == 0) { | 887 | == 0) { |
888 | filemap_fdatawait(inode->i_mapping); | 888 | waitrc = filemap_fdatawait(inode->i_mapping); |
889 | invalidate_remote_inode(inode); | 889 | invalidate_remote_inode(inode); |
890 | } | 890 | } |
891 | if (rc == 0) | ||
892 | rc = waitrc; | ||
891 | } else | 893 | } else |
892 | rc = 0; | 894 | rc = 0; |
893 | /* mutex_unlock(&inode->i_mutex);*/ | 895 | /* mutex_unlock(&inode->i_mutex);*/ |
@@ -907,8 +909,7 @@ static int cifs_oplock_thread(void *dummyarg) | |||
907 | 0 /* len */ , 0 /* offset */, 0, | 909 | 0 /* len */ , 0 /* offset */, 0, |
908 | 0, LOCKING_ANDX_OPLOCK_RELEASE, | 910 | 0, LOCKING_ANDX_OPLOCK_RELEASE, |
909 | 0 /* wait flag */); | 911 | 0 /* wait flag */); |
910 | cFYI(1, | 912 | cFYI(1, ("Oplock release rc = %d", rc)); |
911 | ("Oplock release rc = %d ", rc)); | ||
912 | } | 913 | } |
913 | } else | 914 | } else |
914 | spin_unlock(&GlobalMid_Lock); | 915 | spin_unlock(&GlobalMid_Lock); |
@@ -1009,12 +1010,16 @@ init_cifs(void) | |||
1009 | rc = register_filesystem(&cifs_fs_type); | 1010 | rc = register_filesystem(&cifs_fs_type); |
1010 | if (rc) | 1011 | if (rc) |
1011 | goto out_destroy_request_bufs; | 1012 | goto out_destroy_request_bufs; |
1012 | 1013 | #ifdef CONFIG_CIFS_UPCALL | |
1014 | rc = register_key_type(&cifs_spnego_key_type); | ||
1015 | if (rc) | ||
1016 | goto out_unregister_filesystem; | ||
1017 | #endif | ||
1013 | oplockThread = kthread_run(cifs_oplock_thread, NULL, "cifsoplockd"); | 1018 | oplockThread = kthread_run(cifs_oplock_thread, NULL, "cifsoplockd"); |
1014 | if (IS_ERR(oplockThread)) { | 1019 | if (IS_ERR(oplockThread)) { |
1015 | rc = PTR_ERR(oplockThread); | 1020 | rc = PTR_ERR(oplockThread); |
1016 | cERROR(1, ("error %d create oplock thread", rc)); | 1021 | cERROR(1, ("error %d create oplock thread", rc)); |
1017 | goto out_unregister_filesystem; | 1022 | goto out_unregister_key_type; |
1018 | } | 1023 | } |
1019 | 1024 | ||
1020 | dnotifyThread = kthread_run(cifs_dnotify_thread, NULL, "cifsdnotifyd"); | 1025 | dnotifyThread = kthread_run(cifs_dnotify_thread, NULL, "cifsdnotifyd"); |
@@ -1028,7 +1033,11 @@ init_cifs(void) | |||
1028 | 1033 | ||
1029 | out_stop_oplock_thread: | 1034 | out_stop_oplock_thread: |
1030 | kthread_stop(oplockThread); | 1035 | kthread_stop(oplockThread); |
1036 | out_unregister_key_type: | ||
1037 | #ifdef CONFIG_CIFS_UPCALL | ||
1038 | unregister_key_type(&cifs_spnego_key_type); | ||
1031 | out_unregister_filesystem: | 1039 | out_unregister_filesystem: |
1040 | #endif | ||
1032 | unregister_filesystem(&cifs_fs_type); | 1041 | unregister_filesystem(&cifs_fs_type); |
1033 | out_destroy_request_bufs: | 1042 | out_destroy_request_bufs: |
1034 | cifs_destroy_request_bufs(); | 1043 | cifs_destroy_request_bufs(); |
@@ -1050,6 +1059,9 @@ exit_cifs(void) | |||
1050 | #ifdef CONFIG_PROC_FS | 1059 | #ifdef CONFIG_PROC_FS |
1051 | cifs_proc_clean(); | 1060 | cifs_proc_clean(); |
1052 | #endif | 1061 | #endif |
1062 | #ifdef CONFIG_CIFS_UPCALL | ||
1063 | unregister_key_type(&cifs_spnego_key_type); | ||
1064 | #endif | ||
1053 | unregister_filesystem(&cifs_fs_type); | 1065 | unregister_filesystem(&cifs_fs_type); |
1054 | cifs_destroy_inodecache(); | 1066 | cifs_destroy_inodecache(); |
1055 | cifs_destroy_mids(); | 1067 | cifs_destroy_mids(); |
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index a20de77a3856..2a21dc66f0de 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * fs/cifs/cifsfs.h | 2 | * fs/cifs/cifsfs.h |
3 | * | 3 | * |
4 | * Copyright (c) International Business Machines Corp., 2002, 2005 | 4 | * Copyright (c) International Business Machines Corp., 2002, 2007 |
5 | * Author(s): Steve French (sfrench@us.ibm.com) | 5 | * Author(s): Steve French (sfrench@us.ibm.com) |
6 | * | 6 | * |
7 | * This library is free software; you can redistribute it and/or modify | 7 | * This library is free software; you can redistribute it and/or modify |
@@ -99,7 +99,12 @@ extern int cifs_setxattr(struct dentry *, const char *, const void *, | |||
99 | size_t, int); | 99 | size_t, int); |
100 | extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t); | 100 | extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t); |
101 | extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); | 101 | extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); |
102 | extern int cifs_ioctl (struct inode *inode, struct file *filep, | 102 | extern int cifs_ioctl(struct inode *inode, struct file *filep, |
103 | unsigned int command, unsigned long arg); | 103 | unsigned int command, unsigned long arg); |
104 | #define CIFS_VERSION "1.50" | 104 | |
105 | #ifdef CONFIG_CIFS_EXPERIMENTAL | ||
106 | extern const struct export_operations cifs_export_ops; | ||
107 | #endif /* EXPERIMENTAL */ | ||
108 | |||
109 | #define CIFS_VERSION "1.52" | ||
105 | #endif /* _CIFSFS_H */ | 110 | #endif /* _CIFSFS_H */ |
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index b98742fc3b5a..1fde2197ad76 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/in.h> | 19 | #include <linux/in.h> |
20 | #include <linux/in6.h> | 20 | #include <linux/in6.h> |
21 | #include "cifs_fs_sb.h" | 21 | #include "cifs_fs_sb.h" |
22 | #include "cifsacl.h" | ||
22 | /* | 23 | /* |
23 | * The sizes of various internal tables and strings | 24 | * The sizes of various internal tables and strings |
24 | */ | 25 | */ |
@@ -89,7 +90,8 @@ enum statusEnum { | |||
89 | }; | 90 | }; |
90 | 91 | ||
91 | enum securityEnum { | 92 | enum securityEnum { |
92 | LANMAN = 0, /* Legacy LANMAN auth */ | 93 | PLAINTXT = 0, /* Legacy with Plaintext passwords */ |
94 | LANMAN, /* Legacy LANMAN auth */ | ||
93 | NTLM, /* Legacy NTLM012 auth with NTLM hash */ | 95 | NTLM, /* Legacy NTLM012 auth with NTLM hash */ |
94 | NTLMv2, /* Legacy NTLM auth with NTLMv2 hash */ | 96 | NTLMv2, /* Legacy NTLM auth with NTLMv2 hash */ |
95 | RawNTLMSSP, /* NTLMSSP without SPNEGO */ | 97 | RawNTLMSSP, /* NTLMSSP without SPNEGO */ |
@@ -108,6 +110,7 @@ struct mac_key { | |||
108 | unsigned int len; | 110 | unsigned int len; |
109 | union { | 111 | union { |
110 | char ntlm[CIFS_SESS_KEY_SIZE + 16]; | 112 | char ntlm[CIFS_SESS_KEY_SIZE + 16]; |
113 | char krb5[CIFS_SESS_KEY_SIZE + 16]; /* BB: length correct? */ | ||
111 | struct { | 114 | struct { |
112 | char key[16]; | 115 | char key[16]; |
113 | struct ntlmv2_resp resp; | 116 | struct ntlmv2_resp resp; |
@@ -115,6 +118,17 @@ struct mac_key { | |||
115 | } data; | 118 | } data; |
116 | }; | 119 | }; |
117 | 120 | ||
121 | struct cifs_cred { | ||
122 | int uid; | ||
123 | int gid; | ||
124 | int mode; | ||
125 | int cecount; | ||
126 | struct cifs_sid osid; | ||
127 | struct cifs_sid gsid; | ||
128 | struct cifs_ntace *ntaces; | ||
129 | struct cifs_ace *aces; | ||
130 | }; | ||
131 | |||
118 | /* | 132 | /* |
119 | ***************************************************************** | 133 | ***************************************************************** |
120 | * Except the CIFS PDUs themselves all the | 134 | * Except the CIFS PDUs themselves all the |
@@ -126,6 +140,7 @@ struct TCP_Server_Info { | |||
126 | /* 15 character server name + 0x20 16th byte indicating type = srv */ | 140 | /* 15 character server name + 0x20 16th byte indicating type = srv */ |
127 | char server_RFC1001_name[SERVER_NAME_LEN_WITH_NULL]; | 141 | char server_RFC1001_name[SERVER_NAME_LEN_WITH_NULL]; |
128 | char unicode_server_Name[SERVER_NAME_LEN_WITH_NULL * 2]; | 142 | char unicode_server_Name[SERVER_NAME_LEN_WITH_NULL * 2]; |
143 | char *hostname; /* hostname portion of UNC string */ | ||
129 | struct socket *ssocket; | 144 | struct socket *ssocket; |
130 | union { | 145 | union { |
131 | struct sockaddr_in sockAddr; | 146 | struct sockaddr_in sockAddr; |
@@ -279,6 +294,7 @@ struct cifsTconInfo { | |||
279 | FILE_SYSTEM_DEVICE_INFO fsDevInfo; | 294 | FILE_SYSTEM_DEVICE_INFO fsDevInfo; |
280 | FILE_SYSTEM_ATTRIBUTE_INFO fsAttrInfo; /* ok if fs name truncated */ | 295 | FILE_SYSTEM_ATTRIBUTE_INFO fsAttrInfo; /* ok if fs name truncated */ |
281 | FILE_SYSTEM_UNIX_INFO fsUnixInfo; | 296 | FILE_SYSTEM_UNIX_INFO fsUnixInfo; |
297 | unsigned ipc:1; /* set if connection to IPC$ eg for RPC/PIPES */ | ||
282 | unsigned retry:1; | 298 | unsigned retry:1; |
283 | unsigned nocase:1; | 299 | unsigned nocase:1; |
284 | unsigned unix_ext:1; /* if off disable Linux extensions to CIFS protocol | 300 | unsigned unix_ext:1; /* if off disable Linux extensions to CIFS protocol |
@@ -329,6 +345,7 @@ struct cifsFileInfo { | |||
329 | struct list_head llist; /* list of byte range locks we have. */ | 345 | struct list_head llist; /* list of byte range locks we have. */ |
330 | unsigned closePend:1; /* file is marked to close */ | 346 | unsigned closePend:1; /* file is marked to close */ |
331 | unsigned invalidHandle:1; /* file closed via session abend */ | 347 | unsigned invalidHandle:1; /* file closed via session abend */ |
348 | unsigned messageMode:1; /* for pipes: message vs byte mode */ | ||
332 | atomic_t wrtPending; /* handle in use - defer close */ | 349 | atomic_t wrtPending; /* handle in use - defer close */ |
333 | struct semaphore fh_sem; /* prevents reopen race after dead ses*/ | 350 | struct semaphore fh_sem; /* prevents reopen race after dead ses*/ |
334 | char *search_resume_name; /* BB removeme BB */ | 351 | char *search_resume_name; /* BB removeme BB */ |
@@ -456,6 +473,17 @@ struct dir_notify_req { | |||
456 | #define CIFS_LARGE_BUFFER 2 | 473 | #define CIFS_LARGE_BUFFER 2 |
457 | #define CIFS_IOVEC 4 /* array of response buffers */ | 474 | #define CIFS_IOVEC 4 /* array of response buffers */ |
458 | 475 | ||
476 | /* Type of Request to SendReceive2 */ | ||
477 | #define CIFS_STD_OP 0 /* normal request timeout */ | ||
478 | #define CIFS_LONG_OP 1 /* long op (up to 45 sec, oplock time) */ | ||
479 | #define CIFS_VLONG_OP 2 /* sloow op - can take up to 180 seconds */ | ||
480 | #define CIFS_BLOCKING_OP 4 /* operation can block */ | ||
481 | #define CIFS_ASYNC_OP 8 /* do not wait for response */ | ||
482 | #define CIFS_TIMEOUT_MASK 0x00F /* only one of 5 above set in req */ | ||
483 | #define CIFS_LOG_ERROR 0x010 /* log NT STATUS if non-zero */ | ||
484 | #define CIFS_LARGE_BUF_OP 0x020 /* large request buffer */ | ||
485 | #define CIFS_NO_RESP 0x040 /* no response buffer required */ | ||
486 | |||
459 | /* Security Flags: indicate type of session setup needed */ | 487 | /* Security Flags: indicate type of session setup needed */ |
460 | #define CIFSSEC_MAY_SIGN 0x00001 | 488 | #define CIFSSEC_MAY_SIGN 0x00001 |
461 | #define CIFSSEC_MAY_NTLM 0x00002 | 489 | #define CIFSSEC_MAY_NTLM 0x00002 |
@@ -464,6 +492,9 @@ struct dir_notify_req { | |||
464 | #ifdef CONFIG_CIFS_WEAK_PW_HASH | 492 | #ifdef CONFIG_CIFS_WEAK_PW_HASH |
465 | #define CIFSSEC_MAY_LANMAN 0x00010 | 493 | #define CIFSSEC_MAY_LANMAN 0x00010 |
466 | #define CIFSSEC_MAY_PLNTXT 0x00020 | 494 | #define CIFSSEC_MAY_PLNTXT 0x00020 |
495 | #else | ||
496 | #define CIFSSEC_MAY_LANMAN 0 | ||
497 | #define CIFSSEC_MAY_PLNTXT 0 | ||
467 | #endif /* weak passwords */ | 498 | #endif /* weak passwords */ |
468 | #define CIFSSEC_MAY_SEAL 0x00040 /* not supported yet */ | 499 | #define CIFSSEC_MAY_SEAL 0x00040 /* not supported yet */ |
469 | 500 | ||
@@ -477,14 +508,23 @@ require use of the stronger protocol */ | |||
477 | #ifdef CONFIG_CIFS_WEAK_PW_HASH | 508 | #ifdef CONFIG_CIFS_WEAK_PW_HASH |
478 | #define CIFSSEC_MUST_LANMAN 0x10010 | 509 | #define CIFSSEC_MUST_LANMAN 0x10010 |
479 | #define CIFSSEC_MUST_PLNTXT 0x20020 | 510 | #define CIFSSEC_MUST_PLNTXT 0x20020 |
511 | #ifdef CONFIG_CIFS_UPCALL | ||
512 | #define CIFSSEC_MASK 0x3F03F /* allows weak security but also krb5 */ | ||
513 | #else | ||
480 | #define CIFSSEC_MASK 0x37037 /* current flags supported if weak */ | 514 | #define CIFSSEC_MASK 0x37037 /* current flags supported if weak */ |
515 | #endif /* UPCALL */ | ||
516 | #else /* do not allow weak pw hash */ | ||
517 | #ifdef CONFIG_CIFS_UPCALL | ||
518 | #define CIFSSEC_MASK 0x0F00F /* flags supported if no weak allowed */ | ||
481 | #else | 519 | #else |
482 | #define CIFSSEC_MASK 0x07007 /* flags supported if no weak config */ | 520 | #define CIFSSEC_MASK 0x07007 /* flags supported if no weak allowed */ |
521 | #endif /* UPCALL */ | ||
483 | #endif /* WEAK_PW_HASH */ | 522 | #endif /* WEAK_PW_HASH */ |
484 | #define CIFSSEC_MUST_SEAL 0x40040 /* not supported yet */ | 523 | #define CIFSSEC_MUST_SEAL 0x40040 /* not supported yet */ |
485 | 524 | ||
486 | #define CIFSSEC_DEF CIFSSEC_MAY_SIGN | CIFSSEC_MAY_NTLM | CIFSSEC_MAY_NTLMV2 | 525 | #define CIFSSEC_DEF CIFSSEC_MAY_SIGN | CIFSSEC_MAY_NTLM | CIFSSEC_MAY_NTLMV2 |
487 | #define CIFSSEC_MAX CIFSSEC_MUST_SIGN | CIFSSEC_MUST_NTLMV2 | 526 | #define CIFSSEC_MAX CIFSSEC_MUST_SIGN | CIFSSEC_MUST_NTLMV2 |
527 | #define CIFSSEC_AUTH_MASK (CIFSSEC_MAY_NTLM | CIFSSEC_MAY_NTLMV2 | CIFSSEC_MAY_LANMAN | CIFSSEC_MAY_PLNTXT | CIFSSEC_MAY_KRB5) | ||
488 | /* | 528 | /* |
489 | ***************************************************************** | 529 | ***************************************************************** |
490 | * All constants go here | 530 | * All constants go here |
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h index 6a2056e58ceb..dbe6b846f37f 100644 --- a/fs/cifs/cifspdu.h +++ b/fs/cifs/cifspdu.h | |||
@@ -215,6 +215,29 @@ | |||
215 | /* file_execute, file_read_attributes*/ | 215 | /* file_execute, file_read_attributes*/ |
216 | /* write_dac, and delete. */ | 216 | /* write_dac, and delete. */ |
217 | 217 | ||
218 | #define FILE_READ_RIGHTS (FILE_READ_DATA | FILE_READ_EA | FILE_READ_ATTRIBUTES) | ||
219 | #define FILE_WRITE_RIGHTS (FILE_WRITE_DATA | FILE_APPEND_DATA \ | ||
220 | | FILE_WRITE_EA | FILE_WRITE_ATTRIBUTES) | ||
221 | #define FILE_EXEC_RIGHTS (FILE_EXECUTE) | ||
222 | |||
223 | #define SET_FILE_READ_RIGHTS (FILE_READ_DATA | FILE_READ_EA | FILE_WRITE_EA \ | ||
224 | | FILE_READ_ATTRIBUTES \ | ||
225 | | FILE_WRITE_ATTRIBUTES \ | ||
226 | | DELETE | READ_CONTROL | WRITE_DAC \ | ||
227 | | WRITE_OWNER | SYNCHRONIZE) | ||
228 | #define SET_FILE_WRITE_RIGHTS (FILE_WRITE_DATA | FILE_APPEND_DATA \ | ||
229 | | FILE_READ_EA | FILE_WRITE_EA \ | ||
230 | | FILE_DELETE_CHILD | FILE_READ_ATTRIBUTES \ | ||
231 | | FILE_WRITE_ATTRIBUTES \ | ||
232 | | DELETE | READ_CONTROL | WRITE_DAC \ | ||
233 | | WRITE_OWNER | SYNCHRONIZE) | ||
234 | #define SET_FILE_EXEC_RIGHTS (FILE_READ_EA | FILE_WRITE_EA | FILE_EXECUTE \ | ||
235 | | FILE_READ_ATTRIBUTES \ | ||
236 | | FILE_WRITE_ATTRIBUTES \ | ||
237 | | DELETE | READ_CONTROL | WRITE_DAC \ | ||
238 | | WRITE_OWNER | SYNCHRONIZE) | ||
239 | |||
240 | |||
218 | /* | 241 | /* |
219 | * Invalid readdir handle | 242 | * Invalid readdir handle |
220 | */ | 243 | */ |
@@ -360,10 +383,10 @@ struct smb_hdr { | |||
360 | __u8 WordCount; | 383 | __u8 WordCount; |
361 | } __attribute__((packed)); | 384 | } __attribute__((packed)); |
362 | /* given a pointer to an smb_hdr retrieve the value of byte count */ | 385 | /* given a pointer to an smb_hdr retrieve the value of byte count */ |
363 | #define BCC(smb_var) ( *(__u16 *)((char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) ) ) | 386 | #define BCC(smb_var) ( *(__u16 *)((char *)smb_var + sizeof(struct smb_hdr) + (2 * smb_var->WordCount))) |
364 | #define BCC_LE(smb_var) ( *(__le16 *)((char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) ) ) | 387 | #define BCC_LE(smb_var) ( *(__le16 *)((char *)smb_var + sizeof(struct smb_hdr) + (2 * smb_var->WordCount))) |
365 | /* given a pointer to an smb_hdr retrieve the pointer to the byte area */ | 388 | /* given a pointer to an smb_hdr retrieve the pointer to the byte area */ |
366 | #define pByteArea(smb_var) ((unsigned char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) + 2 ) | 389 | #define pByteArea(smb_var) ((unsigned char *)smb_var + sizeof(struct smb_hdr) + (2 * smb_var->WordCount) + 2) |
367 | 390 | ||
368 | /* | 391 | /* |
369 | * Computer Name Length (since Netbios name was length 16 with last byte 0x20) | 392 | * Computer Name Length (since Netbios name was length 16 with last byte 0x20) |
@@ -716,6 +739,14 @@ typedef struct smb_com_findclose_req { | |||
716 | #define REQ_OPENDIRONLY 0x00000008 | 739 | #define REQ_OPENDIRONLY 0x00000008 |
717 | #define REQ_EXTENDED_INFO 0x00000010 | 740 | #define REQ_EXTENDED_INFO 0x00000010 |
718 | 741 | ||
742 | /* File type */ | ||
743 | #define DISK_TYPE 0x0000 | ||
744 | #define BYTE_PIPE_TYPE 0x0001 | ||
745 | #define MESSAGE_PIPE_TYPE 0x0002 | ||
746 | #define PRINTER_TYPE 0x0003 | ||
747 | #define COMM_DEV_TYPE 0x0004 | ||
748 | #define UNKNOWN_TYPE 0xFFFF | ||
749 | |||
719 | typedef struct smb_com_open_req { /* also handles create */ | 750 | typedef struct smb_com_open_req { /* also handles create */ |
720 | struct smb_hdr hdr; /* wct = 24 */ | 751 | struct smb_hdr hdr; /* wct = 24 */ |
721 | __u8 AndXCommand; | 752 | __u8 AndXCommand; |
@@ -1197,6 +1228,29 @@ typedef struct smb_com_transaction_qsec_req { | |||
1197 | __le32 AclFlags; | 1228 | __le32 AclFlags; |
1198 | } __attribute__((packed)) QUERY_SEC_DESC_REQ; | 1229 | } __attribute__((packed)) QUERY_SEC_DESC_REQ; |
1199 | 1230 | ||
1231 | |||
1232 | typedef struct smb_com_transaction_ssec_req { | ||
1233 | struct smb_hdr hdr; /* wct = 19 */ | ||
1234 | __u8 MaxSetupCount; | ||
1235 | __u16 Reserved; | ||
1236 | __le32 TotalParameterCount; | ||
1237 | __le32 TotalDataCount; | ||
1238 | __le32 MaxParameterCount; | ||
1239 | __le32 MaxDataCount; | ||
1240 | __le32 ParameterCount; | ||
1241 | __le32 ParameterOffset; | ||
1242 | __le32 DataCount; | ||
1243 | __le32 DataOffset; | ||
1244 | __u8 SetupCount; /* no setup words follow subcommand */ | ||
1245 | /* SNIA spec incorrectly included spurious pad here */ | ||
1246 | __le16 SubCommand; /* 3 = SET_SECURITY_DESC */ | ||
1247 | __le16 ByteCount; /* bcc = 3 + 8 */ | ||
1248 | __u8 Pad[3]; | ||
1249 | __u16 Fid; | ||
1250 | __u16 Reserved2; | ||
1251 | __le32 AclFlags; | ||
1252 | } __attribute__((packed)) SET_SEC_DESC_REQ; | ||
1253 | |||
1200 | typedef struct smb_com_transaction_change_notify_req { | 1254 | typedef struct smb_com_transaction_change_notify_req { |
1201 | struct smb_hdr hdr; /* wct = 23 */ | 1255 | struct smb_hdr hdr; /* wct = 23 */ |
1202 | __u8 MaxSetupCount; | 1256 | __u8 MaxSetupCount; |
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 04a69dafedba..8350eec49663 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
@@ -48,9 +48,11 @@ extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *, | |||
48 | struct smb_hdr * /* input */ , | 48 | struct smb_hdr * /* input */ , |
49 | struct smb_hdr * /* out */ , | 49 | struct smb_hdr * /* out */ , |
50 | int * /* bytes returned */ , const int long_op); | 50 | int * /* bytes returned */ , const int long_op); |
51 | extern int SendReceiveNoRsp(const unsigned int xid, struct cifsSesInfo *ses, | ||
52 | struct smb_hdr *in_buf, int flags); | ||
51 | extern int SendReceive2(const unsigned int /* xid */ , struct cifsSesInfo *, | 53 | extern int SendReceive2(const unsigned int /* xid */ , struct cifsSesInfo *, |
52 | struct kvec *, int /* nvec to send */, | 54 | struct kvec *, int /* nvec to send */, |
53 | int * /* type of buf returned */ , const int long_op); | 55 | int * /* type of buf returned */ , const int flags); |
54 | extern int SendReceiveBlockingLock(const unsigned int /* xid */ , | 56 | extern int SendReceiveBlockingLock(const unsigned int /* xid */ , |
55 | struct cifsTconInfo *, | 57 | struct cifsTconInfo *, |
56 | struct smb_hdr * /* input */ , | 58 | struct smb_hdr * /* input */ , |
@@ -60,12 +62,15 @@ extern int checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length); | |||
60 | extern int is_valid_oplock_break(struct smb_hdr *smb, struct TCP_Server_Info *); | 62 | extern int is_valid_oplock_break(struct smb_hdr *smb, struct TCP_Server_Info *); |
61 | extern int is_size_safe_to_change(struct cifsInodeInfo *, __u64 eof); | 63 | extern int is_size_safe_to_change(struct cifsInodeInfo *, __u64 eof); |
62 | extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *); | 64 | extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *); |
65 | #ifdef CONFIG_CIFS_EXPERIMENTAL | ||
66 | extern struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *); | ||
67 | #endif | ||
63 | extern unsigned int smbCalcSize(struct smb_hdr *ptr); | 68 | extern unsigned int smbCalcSize(struct smb_hdr *ptr); |
64 | extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr); | 69 | extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr); |
65 | extern int decode_negTokenInit(unsigned char *security_blob, int length, | 70 | extern int decode_negTokenInit(unsigned char *security_blob, int length, |
66 | enum securityEnum *secType); | 71 | enum securityEnum *secType); |
67 | extern int cifs_inet_pton(int, char *source, void *dst); | 72 | extern int cifs_inet_pton(int, char *source, void *dst); |
68 | extern int map_smb_to_linux_error(struct smb_hdr *smb); | 73 | extern int map_smb_to_linux_error(struct smb_hdr *smb, int logErr); |
69 | extern void header_assemble(struct smb_hdr *, char /* command */ , | 74 | extern void header_assemble(struct smb_hdr *, char /* command */ , |
70 | const struct cifsTconInfo *, int /* length of | 75 | const struct cifsTconInfo *, int /* length of |
71 | fixed section (word count) in two byte units */); | 76 | fixed section (word count) in two byte units */); |
@@ -91,6 +96,8 @@ extern int cifs_get_inode_info(struct inode **pinode, | |||
91 | extern int cifs_get_inode_info_unix(struct inode **pinode, | 96 | extern int cifs_get_inode_info_unix(struct inode **pinode, |
92 | const unsigned char *search_path, | 97 | const unsigned char *search_path, |
93 | struct super_block *sb, int xid); | 98 | struct super_block *sb, int xid); |
99 | extern void acl_to_uid_mode(struct inode *inode, const char *search_path); | ||
100 | extern int mode_to_acl(struct inode *inode, const char *path); | ||
94 | 101 | ||
95 | extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *, | 102 | extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *, |
96 | const char *); | 103 | const char *); |
@@ -240,15 +247,15 @@ extern int CIFSSMBQueryReparseLinkInfo(const int xid, | |||
240 | extern int CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon, | 247 | extern int CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon, |
241 | const char *fileName, const int disposition, | 248 | const char *fileName, const int disposition, |
242 | const int access_flags, const int omode, | 249 | const int access_flags, const int omode, |
243 | __u16 * netfid, int *pOplock, FILE_ALL_INFO *, | 250 | __u16 *netfid, int *pOplock, FILE_ALL_INFO *, |
244 | const struct nls_table *nls_codepage, int remap); | 251 | const struct nls_table *nls_codepage, int remap); |
245 | extern int SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon, | 252 | extern int SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon, |
246 | const char *fileName, const int disposition, | 253 | const char *fileName, const int disposition, |
247 | const int access_flags, const int omode, | 254 | const int access_flags, const int omode, |
248 | __u16 * netfid, int *pOplock, FILE_ALL_INFO *, | 255 | __u16 *netfid, int *pOplock, FILE_ALL_INFO *, |
249 | const struct nls_table *nls_codepage, int remap); | 256 | const struct nls_table *nls_codepage, int remap); |
250 | extern int CIFSPOSIXCreate(const int xid, struct cifsTconInfo *tcon, | 257 | extern int CIFSPOSIXCreate(const int xid, struct cifsTconInfo *tcon, |
251 | u32 posix_flags, __u64 mode, __u16 * netfid, | 258 | u32 posix_flags, __u64 mode, __u16 *netfid, |
252 | FILE_UNIX_BASIC_INFO *pRetData, | 259 | FILE_UNIX_BASIC_INFO *pRetData, |
253 | __u32 *pOplock, const char *name, | 260 | __u32 *pOplock, const char *name, |
254 | const struct nls_table *nls_codepage, int remap); | 261 | const struct nls_table *nls_codepage, int remap); |
@@ -269,7 +276,7 @@ extern int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon, | |||
269 | const __u64 offset, unsigned int *nbytes, | 276 | const __u64 offset, unsigned int *nbytes, |
270 | struct kvec *iov, const int nvec, const int long_op); | 277 | struct kvec *iov, const int nvec, const int long_op); |
271 | extern int CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon, | 278 | extern int CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon, |
272 | const unsigned char *searchName, __u64 * inode_number, | 279 | const unsigned char *searchName, __u64 *inode_number, |
273 | const struct nls_table *nls_codepage, | 280 | const struct nls_table *nls_codepage, |
274 | int remap_special_chars); | 281 | int remap_special_chars); |
275 | extern int cifs_convertUCSpath(char *target, const __le16 *source, int maxlen, | 282 | extern int cifs_convertUCSpath(char *target, const __le16 *source, int maxlen, |
@@ -304,7 +311,7 @@ extern int cifs_calculate_mac_key(struct mac_key *key, const char *rn, | |||
304 | const char *pass); | 311 | const char *pass); |
305 | extern int CalcNTLMv2_partial_mac_key(struct cifsSesInfo *, | 312 | extern int CalcNTLMv2_partial_mac_key(struct cifsSesInfo *, |
306 | const struct nls_table *); | 313 | const struct nls_table *); |
307 | extern void CalcNTLMv2_response(const struct cifsSesInfo *, char * ); | 314 | extern void CalcNTLMv2_response(const struct cifsSesInfo *, char *); |
308 | extern void setup_ntlmv2_rsp(struct cifsSesInfo *, char *, | 315 | extern void setup_ntlmv2_rsp(struct cifsSesInfo *, char *, |
309 | const struct nls_table *); | 316 | const struct nls_table *); |
310 | #ifdef CONFIG_CIFS_WEAK_PW_HASH | 317 | #ifdef CONFIG_CIFS_WEAK_PW_HASH |
@@ -334,8 +341,7 @@ extern int CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, | |||
334 | const void *ea_value, const __u16 ea_value_len, | 341 | const void *ea_value, const __u16 ea_value_len, |
335 | const struct nls_table *nls_codepage, int remap_special_chars); | 342 | const struct nls_table *nls_codepage, int remap_special_chars); |
336 | extern int CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, | 343 | extern int CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, |
337 | __u16 fid, char *acl_inf, const int buflen, | 344 | __u16 fid, struct cifs_ntsd **acl_inf, __u32 *buflen); |
338 | const int acl_type /* ACCESS vs. DEFAULT */); | ||
339 | extern int CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon, | 345 | extern int CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon, |
340 | const unsigned char *searchName, | 346 | const unsigned char *searchName, |
341 | char *acl_inf, const int buflen, const int acl_type, | 347 | char *acl_inf, const int buflen, const int acl_type, |
@@ -345,5 +351,5 @@ extern int CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon, | |||
345 | const char *local_acl, const int buflen, const int acl_type, | 351 | const char *local_acl, const int buflen, const int acl_type, |
346 | const struct nls_table *nls_codepage, int remap_special_chars); | 352 | const struct nls_table *nls_codepage, int remap_special_chars); |
347 | extern int CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon, | 353 | extern int CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon, |
348 | const int netfid, __u64 * pExtAttrBits, __u64 *pMask); | 354 | const int netfid, __u64 *pExtAttrBits, __u64 *pMask); |
349 | #endif /* _CIFSPROTO_H */ | 355 | #endif /* _CIFSPROTO_H */ |
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 8eb102f940d4..9e8a6bef029a 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
@@ -34,10 +34,10 @@ | |||
34 | #include <asm/uaccess.h> | 34 | #include <asm/uaccess.h> |
35 | #include "cifspdu.h" | 35 | #include "cifspdu.h" |
36 | #include "cifsglob.h" | 36 | #include "cifsglob.h" |
37 | #include "cifsacl.h" | ||
37 | #include "cifsproto.h" | 38 | #include "cifsproto.h" |
38 | #include "cifs_unicode.h" | 39 | #include "cifs_unicode.h" |
39 | #include "cifs_debug.h" | 40 | #include "cifs_debug.h" |
40 | #include "cifsacl.h" | ||
41 | 41 | ||
42 | #ifdef CONFIG_CIFS_POSIX | 42 | #ifdef CONFIG_CIFS_POSIX |
43 | static struct { | 43 | static struct { |
@@ -94,9 +94,8 @@ static void mark_open_files_invalid(struct cifsTconInfo *pTcon) | |||
94 | write_lock(&GlobalSMBSeslock); | 94 | write_lock(&GlobalSMBSeslock); |
95 | list_for_each_safe(tmp, tmp1, &pTcon->openFileList) { | 95 | list_for_each_safe(tmp, tmp1, &pTcon->openFileList) { |
96 | open_file = list_entry(tmp, struct cifsFileInfo, tlist); | 96 | open_file = list_entry(tmp, struct cifsFileInfo, tlist); |
97 | if (open_file) { | 97 | if (open_file) |
98 | open_file->invalidHandle = TRUE; | 98 | open_file->invalidHandle = TRUE; |
99 | } | ||
100 | } | 99 | } |
101 | write_unlock(&GlobalSMBSeslock); | 100 | write_unlock(&GlobalSMBSeslock); |
102 | /* BB Add call to invalidate_inodes(sb) for all superblocks mounted | 101 | /* BB Add call to invalidate_inodes(sb) for all superblocks mounted |
@@ -439,8 +438,13 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) | |||
439 | 438 | ||
440 | pSMB->hdr.Mid = GetNextMid(server); | 439 | pSMB->hdr.Mid = GetNextMid(server); |
441 | pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS); | 440 | pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS); |
441 | |||
442 | if ((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5) | 442 | if ((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5) |
443 | pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC; | 443 | pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC; |
444 | else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_KRB5) { | ||
445 | cFYI(1, ("Kerberos only mechanism, enable extended security")); | ||
446 | pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC; | ||
447 | } | ||
444 | 448 | ||
445 | count = 0; | 449 | count = 0; |
446 | for (i = 0; i < CIFS_NUM_PROT; i++) { | 450 | for (i = 0; i < CIFS_NUM_PROT; i++) { |
@@ -513,7 +517,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) | |||
513 | (int)ts.tv_sec, (int)utc.tv_sec, | 517 | (int)ts.tv_sec, (int)utc.tv_sec, |
514 | (int)(utc.tv_sec - ts.tv_sec))); | 518 | (int)(utc.tv_sec - ts.tv_sec))); |
515 | val = (int)(utc.tv_sec - ts.tv_sec); | 519 | val = (int)(utc.tv_sec - ts.tv_sec); |
516 | seconds = val < 0 ? -val : val; | 520 | seconds = abs(val); |
517 | result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ; | 521 | result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ; |
518 | remain = seconds % MIN_TZ_ADJ; | 522 | remain = seconds % MIN_TZ_ADJ; |
519 | if (remain >= (MIN_TZ_ADJ / 2)) | 523 | if (remain >= (MIN_TZ_ADJ / 2)) |
@@ -574,7 +578,20 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) | |||
574 | server->secType = NTLM; | 578 | server->secType = NTLM; |
575 | else if (secFlags & CIFSSEC_MAY_NTLMV2) | 579 | else if (secFlags & CIFSSEC_MAY_NTLMV2) |
576 | server->secType = NTLMv2; | 580 | server->secType = NTLMv2; |
577 | /* else krb5 ... any others ... */ | 581 | else if (secFlags & CIFSSEC_MAY_KRB5) |
582 | server->secType = Kerberos; | ||
583 | else if (secFlags & CIFSSEC_MAY_LANMAN) | ||
584 | server->secType = LANMAN; | ||
585 | /* #ifdef CONFIG_CIFS_EXPERIMENTAL | ||
586 | else if (secFlags & CIFSSEC_MAY_PLNTXT) | ||
587 | server->secType = ?? | ||
588 | #endif */ | ||
589 | else { | ||
590 | rc = -EOPNOTSUPP; | ||
591 | cERROR(1, ("Invalid security type")); | ||
592 | goto neg_err_exit; | ||
593 | } | ||
594 | /* else ... any others ...? */ | ||
578 | 595 | ||
579 | /* one byte, so no need to convert this or EncryptionKeyLen from | 596 | /* one byte, so no need to convert this or EncryptionKeyLen from |
580 | little endian */ | 597 | little endian */ |
@@ -604,30 +621,33 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) | |||
604 | if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) && | 621 | if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) && |
605 | (server->capabilities & CAP_EXTENDED_SECURITY)) { | 622 | (server->capabilities & CAP_EXTENDED_SECURITY)) { |
606 | count = pSMBr->ByteCount; | 623 | count = pSMBr->ByteCount; |
607 | if (count < 16) | 624 | if (count < 16) { |
608 | rc = -EIO; | 625 | rc = -EIO; |
609 | else if (count == 16) { | 626 | goto neg_err_exit; |
610 | server->secType = RawNTLMSSP; | 627 | } |
611 | if (server->socketUseCount.counter > 1) { | 628 | |
612 | if (memcmp(server->server_GUID, | 629 | if (server->socketUseCount.counter > 1) { |
613 | pSMBr->u.extended_response. | 630 | if (memcmp(server->server_GUID, |
614 | GUID, 16) != 0) { | 631 | pSMBr->u.extended_response. |
615 | cFYI(1, ("server UID changed")); | 632 | GUID, 16) != 0) { |
616 | memcpy(server->server_GUID, | 633 | cFYI(1, ("server UID changed")); |
617 | pSMBr->u.extended_response.GUID, | ||
618 | 16); | ||
619 | } | ||
620 | } else | ||
621 | memcpy(server->server_GUID, | 634 | memcpy(server->server_GUID, |
622 | pSMBr->u.extended_response.GUID, 16); | 635 | pSMBr->u.extended_response.GUID, |
636 | 16); | ||
637 | } | ||
638 | } else | ||
639 | memcpy(server->server_GUID, | ||
640 | pSMBr->u.extended_response.GUID, 16); | ||
641 | |||
642 | if (count == 16) { | ||
643 | server->secType = RawNTLMSSP; | ||
623 | } else { | 644 | } else { |
624 | rc = decode_negTokenInit(pSMBr->u.extended_response. | 645 | rc = decode_negTokenInit(pSMBr->u.extended_response. |
625 | SecurityBlob, | 646 | SecurityBlob, |
626 | count - 16, | 647 | count - 16, |
627 | &server->secType); | 648 | &server->secType); |
628 | if (rc == 1) { | 649 | if (rc == 1) { |
629 | /* BB Need to fill struct for sessetup here */ | 650 | rc = 0; |
630 | rc = -EOPNOTSUPP; | ||
631 | } else { | 651 | } else { |
632 | rc = -EINVAL; | 652 | rc = -EINVAL; |
633 | } | 653 | } |
@@ -642,10 +662,12 @@ signing_check: | |||
642 | /* MUST_SIGN already includes the MAY_SIGN FLAG | 662 | /* MUST_SIGN already includes the MAY_SIGN FLAG |
643 | so if this is zero it means that signing is disabled */ | 663 | so if this is zero it means that signing is disabled */ |
644 | cFYI(1, ("Signing disabled")); | 664 | cFYI(1, ("Signing disabled")); |
645 | if (server->secMode & SECMODE_SIGN_REQUIRED) | 665 | if (server->secMode & SECMODE_SIGN_REQUIRED) { |
646 | cERROR(1, ("Server requires " | 666 | cERROR(1, ("Server requires " |
647 | "/proc/fs/cifs/PacketSigningEnabled " | 667 | "packet signing to be enabled in " |
648 | "to be on")); | 668 | "/proc/fs/cifs/SecurityFlags.")); |
669 | rc = -EOPNOTSUPP; | ||
670 | } | ||
649 | server->secMode &= | 671 | server->secMode &= |
650 | ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED); | 672 | ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED); |
651 | } else if ((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) { | 673 | } else if ((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) { |
@@ -676,9 +698,7 @@ int | |||
676 | CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon) | 698 | CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon) |
677 | { | 699 | { |
678 | struct smb_hdr *smb_buffer; | 700 | struct smb_hdr *smb_buffer; |
679 | struct smb_hdr *smb_buffer_response; /* BB removeme BB */ | ||
680 | int rc = 0; | 701 | int rc = 0; |
681 | int length; | ||
682 | 702 | ||
683 | cFYI(1, ("In tree disconnect")); | 703 | cFYI(1, ("In tree disconnect")); |
684 | /* | 704 | /* |
@@ -715,16 +735,12 @@ CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon) | |||
715 | if (rc) { | 735 | if (rc) { |
716 | up(&tcon->tconSem); | 736 | up(&tcon->tconSem); |
717 | return rc; | 737 | return rc; |
718 | } else { | ||
719 | smb_buffer_response = smb_buffer; /* BB removeme BB */ | ||
720 | } | 738 | } |
721 | rc = SendReceive(xid, tcon->ses, smb_buffer, smb_buffer_response, | 739 | |
722 | &length, 0); | 740 | rc = SendReceiveNoRsp(xid, tcon->ses, smb_buffer, 0); |
723 | if (rc) | 741 | if (rc) |
724 | cFYI(1, ("Tree disconnect failed %d", rc)); | 742 | cFYI(1, ("Tree disconnect failed %d", rc)); |
725 | 743 | ||
726 | if (smb_buffer) | ||
727 | cifs_small_buf_release(smb_buffer); | ||
728 | up(&tcon->tconSem); | 744 | up(&tcon->tconSem); |
729 | 745 | ||
730 | /* No need to return error on this operation if tid invalidated and | 746 | /* No need to return error on this operation if tid invalidated and |
@@ -738,10 +754,8 @@ CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon) | |||
738 | int | 754 | int |
739 | CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses) | 755 | CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses) |
740 | { | 756 | { |
741 | struct smb_hdr *smb_buffer_response; | ||
742 | LOGOFF_ANDX_REQ *pSMB; | 757 | LOGOFF_ANDX_REQ *pSMB; |
743 | int rc = 0; | 758 | int rc = 0; |
744 | int length; | ||
745 | 759 | ||
746 | cFYI(1, ("In SMBLogoff for session disconnect")); | 760 | cFYI(1, ("In SMBLogoff for session disconnect")); |
747 | if (ses) | 761 | if (ses) |
@@ -760,8 +774,6 @@ CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses) | |||
760 | return rc; | 774 | return rc; |
761 | } | 775 | } |
762 | 776 | ||
763 | smb_buffer_response = (struct smb_hdr *)pSMB; /* BB removeme BB */ | ||
764 | |||
765 | if (ses->server) { | 777 | if (ses->server) { |
766 | pSMB->hdr.Mid = GetNextMid(ses->server); | 778 | pSMB->hdr.Mid = GetNextMid(ses->server); |
767 | 779 | ||
@@ -773,8 +785,7 @@ CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses) | |||
773 | pSMB->hdr.Uid = ses->Suid; | 785 | pSMB->hdr.Uid = ses->Suid; |
774 | 786 | ||
775 | pSMB->AndXCommand = 0xFF; | 787 | pSMB->AndXCommand = 0xFF; |
776 | rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB, | 788 | rc = SendReceiveNoRsp(xid, ses, (struct smb_hdr *) pSMB, 0); |
777 | smb_buffer_response, &length, 0); | ||
778 | if (ses->server) { | 789 | if (ses->server) { |
779 | atomic_dec(&ses->server->socketUseCount); | 790 | atomic_dec(&ses->server->socketUseCount); |
780 | if (atomic_read(&ses->server->socketUseCount) == 0) { | 791 | if (atomic_read(&ses->server->socketUseCount) == 0) { |
@@ -785,7 +796,6 @@ CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses) | |||
785 | } | 796 | } |
786 | } | 797 | } |
787 | up(&ses->sesSem); | 798 | up(&ses->sesSem); |
788 | cifs_small_buf_release(pSMB); | ||
789 | 799 | ||
790 | /* if session dead then we do not need to do ulogoff, | 800 | /* if session dead then we do not need to do ulogoff, |
791 | since server closed smb session, no sense reporting | 801 | since server closed smb session, no sense reporting |
@@ -1052,7 +1062,7 @@ PsxCreat: | |||
1052 | InformationLevel) - 4; | 1062 | InformationLevel) - 4; |
1053 | offset = param_offset + params; | 1063 | offset = param_offset + params; |
1054 | pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset); | 1064 | pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset); |
1055 | pdata->Level = SMB_QUERY_FILE_UNIX_BASIC; | 1065 | pdata->Level = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC); |
1056 | pdata->Permissions = cpu_to_le64(mode); | 1066 | pdata->Permissions = cpu_to_le64(mode); |
1057 | pdata->PosixOpenFlags = cpu_to_le32(posix_flags); | 1067 | pdata->PosixOpenFlags = cpu_to_le32(posix_flags); |
1058 | pdata->OpenFlags = cpu_to_le32(*pOplock); | 1068 | pdata->OpenFlags = cpu_to_le32(*pOplock); |
@@ -1098,8 +1108,8 @@ PsxCreat: | |||
1098 | if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction) | 1108 | if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction) |
1099 | *pOplock |= CIFS_CREATE_ACTION; | 1109 | *pOplock |= CIFS_CREATE_ACTION; |
1100 | /* check to make sure response data is there */ | 1110 | /* check to make sure response data is there */ |
1101 | if (psx_rsp->ReturnedLevel != SMB_QUERY_FILE_UNIX_BASIC) { | 1111 | if (psx_rsp->ReturnedLevel != cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC)) { |
1102 | pRetData->Type = -1; /* unknown */ | 1112 | pRetData->Type = cpu_to_le32(-1); /* unknown */ |
1103 | #ifdef CONFIG_CIFS_DEBUG2 | 1113 | #ifdef CONFIG_CIFS_DEBUG2 |
1104 | cFYI(1, ("unknown type")); | 1114 | cFYI(1, ("unknown type")); |
1105 | #endif | 1115 | #endif |
@@ -1107,12 +1117,12 @@ PsxCreat: | |||
1107 | if (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP) | 1117 | if (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP) |
1108 | + sizeof(FILE_UNIX_BASIC_INFO)) { | 1118 | + sizeof(FILE_UNIX_BASIC_INFO)) { |
1109 | cERROR(1, ("Open response data too small")); | 1119 | cERROR(1, ("Open response data too small")); |
1110 | pRetData->Type = -1; | 1120 | pRetData->Type = cpu_to_le32(-1); |
1111 | goto psx_create_err; | 1121 | goto psx_create_err; |
1112 | } | 1122 | } |
1113 | memcpy((char *) pRetData, | 1123 | memcpy((char *) pRetData, |
1114 | (char *)psx_rsp + sizeof(OPEN_PSX_RSP), | 1124 | (char *)psx_rsp + sizeof(OPEN_PSX_RSP), |
1115 | sizeof (FILE_UNIX_BASIC_INFO)); | 1125 | sizeof(FILE_UNIX_BASIC_INFO)); |
1116 | } | 1126 | } |
1117 | 1127 | ||
1118 | psx_create_err: | 1128 | psx_create_err: |
@@ -1193,9 +1203,9 @@ OldOpenRetry: | |||
1193 | } | 1203 | } |
1194 | if (*pOplock & REQ_OPLOCK) | 1204 | if (*pOplock & REQ_OPLOCK) |
1195 | pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK); | 1205 | pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK); |
1196 | else if (*pOplock & REQ_BATCHOPLOCK) { | 1206 | else if (*pOplock & REQ_BATCHOPLOCK) |
1197 | pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK); | 1207 | pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK); |
1198 | } | 1208 | |
1199 | pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO); | 1209 | pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO); |
1200 | /* BB fixme add conversion for access_flags to bits 0 - 2 of mode */ | 1210 | /* BB fixme add conversion for access_flags to bits 0 - 2 of mode */ |
1201 | /* 0 = read | 1211 | /* 0 = read |
@@ -1233,7 +1243,7 @@ OldOpenRetry: | |||
1233 | pSMB->ByteCount = cpu_to_le16(count); | 1243 | pSMB->ByteCount = cpu_to_le16(count); |
1234 | /* long_op set to 1 to allow for oplock break timeouts */ | 1244 | /* long_op set to 1 to allow for oplock break timeouts */ |
1235 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 1245 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
1236 | (struct smb_hdr *) pSMBr, &bytes_returned, 1); | 1246 | (struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP); |
1237 | cifs_stats_inc(&tcon->num_opens); | 1247 | cifs_stats_inc(&tcon->num_opens); |
1238 | if (rc) { | 1248 | if (rc) { |
1239 | cFYI(1, ("Error in Open = %d", rc)); | 1249 | cFYI(1, ("Error in Open = %d", rc)); |
@@ -1310,9 +1320,8 @@ openRetry: | |||
1310 | } | 1320 | } |
1311 | if (*pOplock & REQ_OPLOCK) | 1321 | if (*pOplock & REQ_OPLOCK) |
1312 | pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK); | 1322 | pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK); |
1313 | else if (*pOplock & REQ_BATCHOPLOCK) { | 1323 | else if (*pOplock & REQ_BATCHOPLOCK) |
1314 | pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK); | 1324 | pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK); |
1315 | } | ||
1316 | pSMB->DesiredAccess = cpu_to_le32(access_flags); | 1325 | pSMB->DesiredAccess = cpu_to_le32(access_flags); |
1317 | pSMB->AllocationSize = 0; | 1326 | pSMB->AllocationSize = 0; |
1318 | /* set file as system file if special file such | 1327 | /* set file as system file if special file such |
@@ -1347,7 +1356,7 @@ openRetry: | |||
1347 | pSMB->ByteCount = cpu_to_le16(count); | 1356 | pSMB->ByteCount = cpu_to_le16(count); |
1348 | /* long_op set to 1 to allow for oplock break timeouts */ | 1357 | /* long_op set to 1 to allow for oplock break timeouts */ |
1349 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 1358 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
1350 | (struct smb_hdr *) pSMBr, &bytes_returned, 1); | 1359 | (struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP); |
1351 | cifs_stats_inc(&tcon->num_opens); | 1360 | cifs_stats_inc(&tcon->num_opens); |
1352 | if (rc) { | 1361 | if (rc) { |
1353 | cFYI(1, ("Error in Open = %d", rc)); | 1362 | cFYI(1, ("Error in Open = %d", rc)); |
@@ -1424,9 +1433,8 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid, | |||
1424 | 1433 | ||
1425 | iov[0].iov_base = (char *)pSMB; | 1434 | iov[0].iov_base = (char *)pSMB; |
1426 | iov[0].iov_len = pSMB->hdr.smb_buf_length + 4; | 1435 | iov[0].iov_len = pSMB->hdr.smb_buf_length + 4; |
1427 | rc = SendReceive2(xid, tcon->ses, iov, | 1436 | rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */, |
1428 | 1 /* num iovecs */, | 1437 | &resp_buf_type, CIFS_STD_OP | CIFS_LOG_ERROR); |
1429 | &resp_buf_type, 0); | ||
1430 | cifs_stats_inc(&tcon->num_reads); | 1438 | cifs_stats_inc(&tcon->num_reads); |
1431 | pSMBr = (READ_RSP *)iov[0].iov_base; | 1439 | pSMBr = (READ_RSP *)iov[0].iov_base; |
1432 | if (rc) { | 1440 | if (rc) { |
@@ -1446,11 +1454,11 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid, | |||
1446 | *nbytes = 0; | 1454 | *nbytes = 0; |
1447 | } else { | 1455 | } else { |
1448 | pReadData = (char *) (&pSMBr->hdr.Protocol) + | 1456 | pReadData = (char *) (&pSMBr->hdr.Protocol) + |
1449 | le16_to_cpu(pSMBr->DataOffset); | 1457 | le16_to_cpu(pSMBr->DataOffset); |
1450 | /* if (rc = copy_to_user(buf, pReadData, data_length)) { | 1458 | /* if (rc = copy_to_user(buf, pReadData, data_length)) { |
1451 | cERROR(1,("Faulting on read rc = %d",rc)); | 1459 | cERROR(1,("Faulting on read rc = %d",rc)); |
1452 | rc = -EFAULT; | 1460 | rc = -EFAULT; |
1453 | }*/ /* can not use copy_to_user when using page cache*/ | 1461 | }*/ /* can not use copy_to_user when using page cache*/ |
1454 | if (*buf) | 1462 | if (*buf) |
1455 | memcpy(*buf, pReadData, data_length); | 1463 | memcpy(*buf, pReadData, data_length); |
1456 | } | 1464 | } |
@@ -1687,7 +1695,7 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, | |||
1687 | int timeout = 0; | 1695 | int timeout = 0; |
1688 | __u16 count; | 1696 | __u16 count; |
1689 | 1697 | ||
1690 | cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d", waitFlag, numLock)); | 1698 | cFYI(1, ("CIFSSMBLock timeout %d numLock %d", waitFlag, numLock)); |
1691 | rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB); | 1699 | rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB); |
1692 | 1700 | ||
1693 | if (rc) | 1701 | if (rc) |
@@ -1696,10 +1704,10 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, | |||
1696 | pSMBr = (LOCK_RSP *)pSMB; /* BB removeme BB */ | 1704 | pSMBr = (LOCK_RSP *)pSMB; /* BB removeme BB */ |
1697 | 1705 | ||
1698 | if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) { | 1706 | if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) { |
1699 | timeout = -1; /* no response expected */ | 1707 | timeout = CIFS_ASYNC_OP; /* no response expected */ |
1700 | pSMB->Timeout = 0; | 1708 | pSMB->Timeout = 0; |
1701 | } else if (waitFlag == TRUE) { | 1709 | } else if (waitFlag == TRUE) { |
1702 | timeout = 3; /* blocking operation, no timeout */ | 1710 | timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */ |
1703 | pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */ | 1711 | pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */ |
1704 | } else { | 1712 | } else { |
1705 | pSMB->Timeout = 0; | 1713 | pSMB->Timeout = 0; |
@@ -1729,15 +1737,16 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, | |||
1729 | if (waitFlag) { | 1737 | if (waitFlag) { |
1730 | rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB, | 1738 | rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB, |
1731 | (struct smb_hdr *) pSMBr, &bytes_returned); | 1739 | (struct smb_hdr *) pSMBr, &bytes_returned); |
1740 | cifs_small_buf_release(pSMB); | ||
1732 | } else { | 1741 | } else { |
1733 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 1742 | rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *)pSMB, |
1734 | (struct smb_hdr *) pSMBr, &bytes_returned, timeout); | 1743 | timeout); |
1744 | /* SMB buffer freed by function above */ | ||
1735 | } | 1745 | } |
1736 | cifs_stats_inc(&tcon->num_locks); | 1746 | cifs_stats_inc(&tcon->num_locks); |
1737 | if (rc) { | 1747 | if (rc) { |
1738 | cFYI(1, ("Send error in Lock = %d", rc)); | 1748 | cFYI(1, ("Send error in Lock = %d", rc)); |
1739 | } | 1749 | } |
1740 | cifs_small_buf_release(pSMB); | ||
1741 | 1750 | ||
1742 | /* Note: On -EAGAIN error only caller can retry on handle based calls | 1751 | /* Note: On -EAGAIN error only caller can retry on handle based calls |
1743 | since file handle passed in no longer valid */ | 1752 | since file handle passed in no longer valid */ |
@@ -1756,7 +1765,9 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon, | |||
1756 | int rc = 0; | 1765 | int rc = 0; |
1757 | int timeout = 0; | 1766 | int timeout = 0; |
1758 | int bytes_returned = 0; | 1767 | int bytes_returned = 0; |
1768 | int resp_buf_type = 0; | ||
1759 | __u16 params, param_offset, offset, byte_count, count; | 1769 | __u16 params, param_offset, offset, byte_count, count; |
1770 | struct kvec iov[1]; | ||
1760 | 1771 | ||
1761 | cFYI(1, ("Posix Lock")); | 1772 | cFYI(1, ("Posix Lock")); |
1762 | 1773 | ||
@@ -1798,7 +1809,7 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon, | |||
1798 | 1809 | ||
1799 | parm_data->lock_type = cpu_to_le16(lock_type); | 1810 | parm_data->lock_type = cpu_to_le16(lock_type); |
1800 | if (waitFlag) { | 1811 | if (waitFlag) { |
1801 | timeout = 3; /* blocking operation, no timeout */ | 1812 | timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */ |
1802 | parm_data->lock_flags = cpu_to_le16(1); | 1813 | parm_data->lock_flags = cpu_to_le16(1); |
1803 | pSMB->Timeout = cpu_to_le32(-1); | 1814 | pSMB->Timeout = cpu_to_le32(-1); |
1804 | } else | 1815 | } else |
@@ -1818,8 +1829,13 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon, | |||
1818 | rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB, | 1829 | rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB, |
1819 | (struct smb_hdr *) pSMBr, &bytes_returned); | 1830 | (struct smb_hdr *) pSMBr, &bytes_returned); |
1820 | } else { | 1831 | } else { |
1821 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 1832 | iov[0].iov_base = (char *)pSMB; |
1822 | (struct smb_hdr *) pSMBr, &bytes_returned, timeout); | 1833 | iov[0].iov_len = pSMB->hdr.smb_buf_length + 4; |
1834 | rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */, | ||
1835 | &resp_buf_type, timeout); | ||
1836 | pSMB = NULL; /* request buf already freed by SendReceive2. Do | ||
1837 | not try to free it twice below on exit */ | ||
1838 | pSMBr = (struct smb_com_transaction2_sfi_rsp *)iov[0].iov_base; | ||
1823 | } | 1839 | } |
1824 | 1840 | ||
1825 | if (rc) { | 1841 | if (rc) { |
@@ -1854,6 +1870,11 @@ plk_err_exit: | |||
1854 | if (pSMB) | 1870 | if (pSMB) |
1855 | cifs_small_buf_release(pSMB); | 1871 | cifs_small_buf_release(pSMB); |
1856 | 1872 | ||
1873 | if (resp_buf_type == CIFS_SMALL_BUFFER) | ||
1874 | cifs_small_buf_release(iov[0].iov_base); | ||
1875 | else if (resp_buf_type == CIFS_LARGE_BUFFER) | ||
1876 | cifs_buf_release(iov[0].iov_base); | ||
1877 | |||
1857 | /* Note: On -EAGAIN error only caller can retry on handle based calls | 1878 | /* Note: On -EAGAIN error only caller can retry on handle based calls |
1858 | since file handle passed in no longer valid */ | 1879 | since file handle passed in no longer valid */ |
1859 | 1880 | ||
@@ -1866,8 +1887,6 @@ CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id) | |||
1866 | { | 1887 | { |
1867 | int rc = 0; | 1888 | int rc = 0; |
1868 | CLOSE_REQ *pSMB = NULL; | 1889 | CLOSE_REQ *pSMB = NULL; |
1869 | CLOSE_RSP *pSMBr = NULL; | ||
1870 | int bytes_returned; | ||
1871 | cFYI(1, ("In CIFSSMBClose")); | 1890 | cFYI(1, ("In CIFSSMBClose")); |
1872 | 1891 | ||
1873 | /* do not retry on dead session on close */ | 1892 | /* do not retry on dead session on close */ |
@@ -1877,13 +1896,10 @@ CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id) | |||
1877 | if (rc) | 1896 | if (rc) |
1878 | return rc; | 1897 | return rc; |
1879 | 1898 | ||
1880 | pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */ | ||
1881 | |||
1882 | pSMB->FileID = (__u16) smb_file_id; | 1899 | pSMB->FileID = (__u16) smb_file_id; |
1883 | pSMB->LastWriteTime = 0xFFFFFFFF; | 1900 | pSMB->LastWriteTime = 0xFFFFFFFF; |
1884 | pSMB->ByteCount = 0; | 1901 | pSMB->ByteCount = 0; |
1885 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 1902 | rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); |
1886 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | ||
1887 | cifs_stats_inc(&tcon->num_closes); | 1903 | cifs_stats_inc(&tcon->num_closes); |
1888 | if (rc) { | 1904 | if (rc) { |
1889 | if (rc != -EINTR) { | 1905 | if (rc != -EINTR) { |
@@ -1892,8 +1908,6 @@ CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id) | |||
1892 | } | 1908 | } |
1893 | } | 1909 | } |
1894 | 1910 | ||
1895 | cifs_small_buf_release(pSMB); | ||
1896 | |||
1897 | /* Since session is dead, file will be closed on server already */ | 1911 | /* Since session is dead, file will be closed on server already */ |
1898 | if (rc == -EAGAIN) | 1912 | if (rc == -EAGAIN) |
1899 | rc = 0; | 1913 | rc = 0; |
@@ -2465,6 +2479,7 @@ querySymLinkRetry: | |||
2465 | return rc; | 2479 | return rc; |
2466 | } | 2480 | } |
2467 | 2481 | ||
2482 | #ifdef CONFIG_CIFS_EXPERIMENTAL | ||
2468 | /* Initialize NT TRANSACT SMB into small smb request buffer. | 2483 | /* Initialize NT TRANSACT SMB into small smb request buffer. |
2469 | This assumes that all NT TRANSACTS that we init here have | 2484 | This assumes that all NT TRANSACTS that we init here have |
2470 | total parm and data under about 400 bytes (to fit in small cifs | 2485 | total parm and data under about 400 bytes (to fit in small cifs |
@@ -2473,7 +2488,7 @@ querySymLinkRetry: | |||
2473 | MaxSetupCount (size of returned setup area) and | 2488 | MaxSetupCount (size of returned setup area) and |
2474 | MaxParameterCount (returned parms size) must be set by caller */ | 2489 | MaxParameterCount (returned parms size) must be set by caller */ |
2475 | static int | 2490 | static int |
2476 | smb_init_ntransact(const __u16 sub_command, const int setup_count, | 2491 | smb_init_nttransact(const __u16 sub_command, const int setup_count, |
2477 | const int parm_len, struct cifsTconInfo *tcon, | 2492 | const int parm_len, struct cifsTconInfo *tcon, |
2478 | void **ret_buf) | 2493 | void **ret_buf) |
2479 | { | 2494 | { |
@@ -2504,12 +2519,15 @@ smb_init_ntransact(const __u16 sub_command, const int setup_count, | |||
2504 | 2519 | ||
2505 | static int | 2520 | static int |
2506 | validate_ntransact(char *buf, char **ppparm, char **ppdata, | 2521 | validate_ntransact(char *buf, char **ppparm, char **ppdata, |
2507 | int *pdatalen, int *pparmlen) | 2522 | __u32 *pparmlen, __u32 *pdatalen) |
2508 | { | 2523 | { |
2509 | char *end_of_smb; | 2524 | char *end_of_smb; |
2510 | __u32 data_count, data_offset, parm_count, parm_offset; | 2525 | __u32 data_count, data_offset, parm_count, parm_offset; |
2511 | struct smb_com_ntransact_rsp *pSMBr; | 2526 | struct smb_com_ntransact_rsp *pSMBr; |
2512 | 2527 | ||
2528 | *pdatalen = 0; | ||
2529 | *pparmlen = 0; | ||
2530 | |||
2513 | if (buf == NULL) | 2531 | if (buf == NULL) |
2514 | return -EINVAL; | 2532 | return -EINVAL; |
2515 | 2533 | ||
@@ -2538,7 +2556,7 @@ validate_ntransact(char *buf, char **ppparm, char **ppdata, | |||
2538 | cFYI(1, ("data starts after end of smb")); | 2556 | cFYI(1, ("data starts after end of smb")); |
2539 | return -EINVAL; | 2557 | return -EINVAL; |
2540 | } else if (data_count + *ppdata > end_of_smb) { | 2558 | } else if (data_count + *ppdata > end_of_smb) { |
2541 | cFYI(1,("data %p + count %d (%p) ends after end of smb %p start %p", | 2559 | cFYI(1, ("data %p + count %d (%p) ends after end of smb %p start %p", |
2542 | *ppdata, data_count, (data_count + *ppdata), | 2560 | *ppdata, data_count, (data_count + *ppdata), |
2543 | end_of_smb, pSMBr)); | 2561 | end_of_smb, pSMBr)); |
2544 | return -EINVAL; | 2562 | return -EINVAL; |
@@ -2546,8 +2564,11 @@ validate_ntransact(char *buf, char **ppparm, char **ppdata, | |||
2546 | cFYI(1, ("parm count and data count larger than SMB")); | 2564 | cFYI(1, ("parm count and data count larger than SMB")); |
2547 | return -EINVAL; | 2565 | return -EINVAL; |
2548 | } | 2566 | } |
2567 | *pdatalen = data_count; | ||
2568 | *pparmlen = parm_count; | ||
2549 | return 0; | 2569 | return 0; |
2550 | } | 2570 | } |
2571 | #endif /* CIFS_EXPERIMENTAL */ | ||
2551 | 2572 | ||
2552 | int | 2573 | int |
2553 | CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon, | 2574 | CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon, |
@@ -2615,7 +2636,7 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon, | |||
2615 | reparse_buf->TargetNameOffset + | 2636 | reparse_buf->TargetNameOffset + |
2616 | reparse_buf->TargetNameLen) > | 2637 | reparse_buf->TargetNameLen) > |
2617 | end_of_smb) { | 2638 | end_of_smb) { |
2618 | cFYI(1,("reparse buf goes beyond SMB")); | 2639 | cFYI(1, ("reparse buf beyond SMB")); |
2619 | rc = -EIO; | 2640 | rc = -EIO; |
2620 | goto qreparse_out; | 2641 | goto qreparse_out; |
2621 | } | 2642 | } |
@@ -3042,25 +3063,11 @@ GetExtAttrOut: | |||
3042 | 3063 | ||
3043 | #endif /* CONFIG_POSIX */ | 3064 | #endif /* CONFIG_POSIX */ |
3044 | 3065 | ||
3045 | 3066 | #ifdef CONFIG_CIFS_EXPERIMENTAL | |
3046 | /* security id for everyone */ | ||
3047 | static const struct cifs_sid sid_everyone = | ||
3048 | {1, 1, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0}}; | ||
3049 | /* group users */ | ||
3050 | static const struct cifs_sid sid_user = | ||
3051 | {1, 2 , {0, 0, 0, 0, 0, 5}, {32, 545, 0, 0}}; | ||
3052 | |||
3053 | /* Convert CIFS ACL to POSIX form */ | ||
3054 | static int parse_sec_desc(struct cifs_sid *psec_desc, int acl_len) | ||
3055 | { | ||
3056 | return 0; | ||
3057 | } | ||
3058 | |||
3059 | /* Get Security Descriptor (by handle) from remote server for a file or dir */ | 3067 | /* Get Security Descriptor (by handle) from remote server for a file or dir */ |
3060 | int | 3068 | int |
3061 | CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid, | 3069 | CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid, |
3062 | /* BB fix up return info */ char *acl_inf, const int buflen, | 3070 | struct cifs_ntsd **acl_inf, __u32 *pbuflen) |
3063 | const int acl_type /* ACCESS/DEFAULT not sure implication */) | ||
3064 | { | 3071 | { |
3065 | int rc = 0; | 3072 | int rc = 0; |
3066 | int buf_type = 0; | 3073 | int buf_type = 0; |
@@ -3069,7 +3076,10 @@ CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid, | |||
3069 | 3076 | ||
3070 | cFYI(1, ("GetCifsACL")); | 3077 | cFYI(1, ("GetCifsACL")); |
3071 | 3078 | ||
3072 | rc = smb_init_ntransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0, | 3079 | *pbuflen = 0; |
3080 | *acl_inf = NULL; | ||
3081 | |||
3082 | rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0, | ||
3073 | 8 /* parm len */, tcon, (void **) &pSMB); | 3083 | 8 /* parm len */, tcon, (void **) &pSMB); |
3074 | if (rc) | 3084 | if (rc) |
3075 | return rc; | 3085 | return rc; |
@@ -3085,40 +3095,58 @@ CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid, | |||
3085 | iov[0].iov_base = (char *)pSMB; | 3095 | iov[0].iov_base = (char *)pSMB; |
3086 | iov[0].iov_len = pSMB->hdr.smb_buf_length + 4; | 3096 | iov[0].iov_len = pSMB->hdr.smb_buf_length + 4; |
3087 | 3097 | ||
3088 | rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type, 0); | 3098 | rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type, |
3099 | CIFS_STD_OP); | ||
3089 | cifs_stats_inc(&tcon->num_acl_get); | 3100 | cifs_stats_inc(&tcon->num_acl_get); |
3090 | if (rc) { | 3101 | if (rc) { |
3091 | cFYI(1, ("Send error in QuerySecDesc = %d", rc)); | 3102 | cFYI(1, ("Send error in QuerySecDesc = %d", rc)); |
3092 | } else { /* decode response */ | 3103 | } else { /* decode response */ |
3093 | struct cifs_sid *psec_desc; | ||
3094 | __le32 * parm; | 3104 | __le32 * parm; |
3095 | int parm_len; | 3105 | __u32 parm_len; |
3096 | int data_len; | 3106 | __u32 acl_len; |
3097 | int acl_len; | ||
3098 | struct smb_com_ntransact_rsp *pSMBr; | 3107 | struct smb_com_ntransact_rsp *pSMBr; |
3108 | char *pdata; | ||
3099 | 3109 | ||
3100 | /* validate_nttransact */ | 3110 | /* validate_nttransact */ |
3101 | rc = validate_ntransact(iov[0].iov_base, (char **)&parm, | 3111 | rc = validate_ntransact(iov[0].iov_base, (char **)&parm, |
3102 | (char **)&psec_desc, | 3112 | &pdata, &parm_len, pbuflen); |
3103 | &parm_len, &data_len); | ||
3104 | if (rc) | 3113 | if (rc) |
3105 | goto qsec_out; | 3114 | goto qsec_out; |
3106 | pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base; | 3115 | pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base; |
3107 | 3116 | ||
3108 | cERROR(1, ("smb %p parm %p data %p", | 3117 | cFYI(1, ("smb %p parm %p data %p", pSMBr, parm, *acl_inf)); |
3109 | pSMBr, parm, psec_desc)); /* BB removeme BB */ | ||
3110 | 3118 | ||
3111 | if (le32_to_cpu(pSMBr->ParameterCount) != 4) { | 3119 | if (le32_to_cpu(pSMBr->ParameterCount) != 4) { |
3112 | rc = -EIO; /* bad smb */ | 3120 | rc = -EIO; /* bad smb */ |
3121 | *pbuflen = 0; | ||
3113 | goto qsec_out; | 3122 | goto qsec_out; |
3114 | } | 3123 | } |
3115 | 3124 | ||
3116 | /* BB check that data area is minimum length and as big as acl_len */ | 3125 | /* BB check that data area is minimum length and as big as acl_len */ |
3117 | 3126 | ||
3118 | acl_len = le32_to_cpu(*(__le32 *)parm); | 3127 | acl_len = le32_to_cpu(*parm); |
3119 | /* BB check if (acl_len > bufsize) */ | 3128 | if (acl_len != *pbuflen) { |
3129 | cERROR(1, ("acl length %d does not match %d", | ||
3130 | acl_len, *pbuflen)); | ||
3131 | if (*pbuflen > acl_len) | ||
3132 | *pbuflen = acl_len; | ||
3133 | } | ||
3120 | 3134 | ||
3121 | parse_sec_desc(psec_desc, acl_len); | 3135 | /* check if buffer is big enough for the acl |
3136 | header followed by the smallest SID */ | ||
3137 | if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) || | ||
3138 | (*pbuflen >= 64 * 1024)) { | ||
3139 | cERROR(1, ("bad acl length %d", *pbuflen)); | ||
3140 | rc = -EINVAL; | ||
3141 | *pbuflen = 0; | ||
3142 | } else { | ||
3143 | *acl_inf = kmalloc(*pbuflen, GFP_KERNEL); | ||
3144 | if (*acl_inf == NULL) { | ||
3145 | *pbuflen = 0; | ||
3146 | rc = -ENOMEM; | ||
3147 | } | ||
3148 | memcpy(*acl_inf, pdata, *pbuflen); | ||
3149 | } | ||
3122 | } | 3150 | } |
3123 | qsec_out: | 3151 | qsec_out: |
3124 | if (buf_type == CIFS_SMALL_BUFFER) | 3152 | if (buf_type == CIFS_SMALL_BUFFER) |
@@ -3128,6 +3156,7 @@ qsec_out: | |||
3128 | /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */ | 3156 | /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */ |
3129 | return rc; | 3157 | return rc; |
3130 | } | 3158 | } |
3159 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ | ||
3131 | 3160 | ||
3132 | /* Legacy Query Path Information call for lookup to old servers such | 3161 | /* Legacy Query Path Information call for lookup to old servers such |
3133 | as Win9x/WinME */ | 3162 | as Win9x/WinME */ |
@@ -3363,13 +3392,16 @@ UnixQPathInfoRetry: | |||
3363 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 3392 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
3364 | 3393 | ||
3365 | if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) { | 3394 | if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) { |
3395 | cERROR(1, ("Malformed FILE_UNIX_BASIC_INFO response.\n" | ||
3396 | "Unix Extensions can be disabled on mount " | ||
3397 | "by specifying the nosfu mount option.")); | ||
3366 | rc = -EIO; /* bad smb */ | 3398 | rc = -EIO; /* bad smb */ |
3367 | } else { | 3399 | } else { |
3368 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); | 3400 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); |
3369 | memcpy((char *) pFindData, | 3401 | memcpy((char *) pFindData, |
3370 | (char *) &pSMBr->hdr.Protocol + | 3402 | (char *) &pSMBr->hdr.Protocol + |
3371 | data_offset, | 3403 | data_offset, |
3372 | sizeof (FILE_UNIX_BASIC_INFO)); | 3404 | sizeof(FILE_UNIX_BASIC_INFO)); |
3373 | } | 3405 | } |
3374 | } | 3406 | } |
3375 | cifs_buf_release(pSMB); | 3407 | cifs_buf_release(pSMB); |
@@ -3637,7 +3669,7 @@ int CIFSFindNext(const int xid, struct cifsTconInfo *tcon, | |||
3637 | pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT); | 3669 | pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT); |
3638 | pSMB->SearchHandle = searchHandle; /* always kept as le */ | 3670 | pSMB->SearchHandle = searchHandle; /* always kept as le */ |
3639 | pSMB->SearchCount = | 3671 | pSMB->SearchCount = |
3640 | cpu_to_le16(CIFSMaxBufSize / sizeof (FILE_UNIX_INFO)); | 3672 | cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO)); |
3641 | pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level); | 3673 | pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level); |
3642 | pSMB->ResumeKey = psrch_inf->resume_key; | 3674 | pSMB->ResumeKey = psrch_inf->resume_key; |
3643 | pSMB->SearchFlags = | 3675 | pSMB->SearchFlags = |
@@ -3725,8 +3757,6 @@ CIFSFindClose(const int xid, struct cifsTconInfo *tcon, | |||
3725 | { | 3757 | { |
3726 | int rc = 0; | 3758 | int rc = 0; |
3727 | FINDCLOSE_REQ *pSMB = NULL; | 3759 | FINDCLOSE_REQ *pSMB = NULL; |
3728 | CLOSE_RSP *pSMBr = NULL; /* BB removeme BB */ | ||
3729 | int bytes_returned; | ||
3730 | 3760 | ||
3731 | cFYI(1, ("In CIFSSMBFindClose")); | 3761 | cFYI(1, ("In CIFSSMBFindClose")); |
3732 | rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB); | 3762 | rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB); |
@@ -3738,16 +3768,13 @@ CIFSFindClose(const int xid, struct cifsTconInfo *tcon, | |||
3738 | if (rc) | 3768 | if (rc) |
3739 | return rc; | 3769 | return rc; |
3740 | 3770 | ||
3741 | pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */ | ||
3742 | pSMB->FileID = searchHandle; | 3771 | pSMB->FileID = searchHandle; |
3743 | pSMB->ByteCount = 0; | 3772 | pSMB->ByteCount = 0; |
3744 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 3773 | rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); |
3745 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | ||
3746 | if (rc) { | 3774 | if (rc) { |
3747 | cERROR(1, ("Send error in FindClose = %d", rc)); | 3775 | cERROR(1, ("Send error in FindClose = %d", rc)); |
3748 | } | 3776 | } |
3749 | cifs_stats_inc(&tcon->num_fclose); | 3777 | cifs_stats_inc(&tcon->num_fclose); |
3750 | cifs_small_buf_release(pSMB); | ||
3751 | 3778 | ||
3752 | /* Since session is dead, search handle closed on server already */ | 3779 | /* Since session is dead, search handle closed on server already */ |
3753 | if (rc == -EAGAIN) | 3780 | if (rc == -EAGAIN) |
@@ -3883,12 +3910,10 @@ getDFSRetry: | |||
3883 | pSMB->hdr.Mid = GetNextMid(ses->server); | 3910 | pSMB->hdr.Mid = GetNextMid(ses->server); |
3884 | pSMB->hdr.Tid = ses->ipc_tid; | 3911 | pSMB->hdr.Tid = ses->ipc_tid; |
3885 | pSMB->hdr.Uid = ses->Suid; | 3912 | pSMB->hdr.Uid = ses->Suid; |
3886 | if (ses->capabilities & CAP_STATUS32) { | 3913 | if (ses->capabilities & CAP_STATUS32) |
3887 | pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS; | 3914 | pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS; |
3888 | } | 3915 | if (ses->capabilities & CAP_DFS) |
3889 | if (ses->capabilities & CAP_DFS) { | ||
3890 | pSMB->hdr.Flags2 |= SMBFLG2_DFS; | 3916 | pSMB->hdr.Flags2 |= SMBFLG2_DFS; |
3891 | } | ||
3892 | 3917 | ||
3893 | if (ses->capabilities & CAP_UNICODE) { | 3918 | if (ses->capabilities & CAP_UNICODE) { |
3894 | pSMB->hdr.Flags2 |= SMBFLG2_UNICODE; | 3919 | pSMB->hdr.Flags2 |= SMBFLG2_UNICODE; |
@@ -4060,10 +4085,6 @@ oldQFSInfoRetry: | |||
4060 | (void **) &pSMBr); | 4085 | (void **) &pSMBr); |
4061 | if (rc) | 4086 | if (rc) |
4062 | return rc; | 4087 | return rc; |
4063 | rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, | ||
4064 | (void **) &pSMBr); | ||
4065 | if (rc) | ||
4066 | return rc; | ||
4067 | 4088 | ||
4068 | params = 2; /* level */ | 4089 | params = 2; /* level */ |
4069 | pSMB->TotalDataCount = 0; | 4090 | pSMB->TotalDataCount = 0; |
@@ -4265,7 +4286,7 @@ QFSAttributeRetry: | |||
4265 | *) (((char *) &pSMBr->hdr.Protocol) + | 4286 | *) (((char *) &pSMBr->hdr.Protocol) + |
4266 | data_offset); | 4287 | data_offset); |
4267 | memcpy(&tcon->fsAttrInfo, response_data, | 4288 | memcpy(&tcon->fsAttrInfo, response_data, |
4268 | sizeof (FILE_SYSTEM_ATTRIBUTE_INFO)); | 4289 | sizeof(FILE_SYSTEM_ATTRIBUTE_INFO)); |
4269 | } | 4290 | } |
4270 | } | 4291 | } |
4271 | cifs_buf_release(pSMB); | 4292 | cifs_buf_release(pSMB); |
@@ -4325,7 +4346,7 @@ QFSDeviceRetry: | |||
4325 | } else { /* decode response */ | 4346 | } else { /* decode response */ |
4326 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 4347 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
4327 | 4348 | ||
4328 | if (rc || (pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO))) | 4349 | if (rc || (pSMBr->ByteCount < sizeof(FILE_SYSTEM_DEVICE_INFO))) |
4329 | rc = -EIO; /* bad smb */ | 4350 | rc = -EIO; /* bad smb */ |
4330 | else { | 4351 | else { |
4331 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); | 4352 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); |
@@ -4334,7 +4355,7 @@ QFSDeviceRetry: | |||
4334 | (((char *) &pSMBr->hdr.Protocol) + | 4355 | (((char *) &pSMBr->hdr.Protocol) + |
4335 | data_offset); | 4356 | data_offset); |
4336 | memcpy(&tcon->fsDevInfo, response_data, | 4357 | memcpy(&tcon->fsDevInfo, response_data, |
4337 | sizeof (FILE_SYSTEM_DEVICE_INFO)); | 4358 | sizeof(FILE_SYSTEM_DEVICE_INFO)); |
4338 | } | 4359 | } |
4339 | } | 4360 | } |
4340 | cifs_buf_release(pSMB); | 4361 | cifs_buf_release(pSMB); |
@@ -4402,7 +4423,7 @@ QFSUnixRetry: | |||
4402 | *) (((char *) &pSMBr->hdr.Protocol) + | 4423 | *) (((char *) &pSMBr->hdr.Protocol) + |
4403 | data_offset); | 4424 | data_offset); |
4404 | memcpy(&tcon->fsUnixInfo, response_data, | 4425 | memcpy(&tcon->fsUnixInfo, response_data, |
4405 | sizeof (FILE_SYSTEM_UNIX_INFO)); | 4426 | sizeof(FILE_SYSTEM_UNIX_INFO)); |
4406 | } | 4427 | } |
4407 | } | 4428 | } |
4408 | cifs_buf_release(pSMB); | 4429 | cifs_buf_release(pSMB); |
@@ -4612,7 +4633,7 @@ SetEOFRetry: | |||
4612 | strncpy(pSMB->FileName, fileName, name_len); | 4633 | strncpy(pSMB->FileName, fileName, name_len); |
4613 | } | 4634 | } |
4614 | params = 6 + name_len; | 4635 | params = 6 + name_len; |
4615 | data_count = sizeof (struct file_end_of_file_info); | 4636 | data_count = sizeof(struct file_end_of_file_info); |
4616 | pSMB->MaxParameterCount = cpu_to_le16(2); | 4637 | pSMB->MaxParameterCount = cpu_to_le16(2); |
4617 | pSMB->MaxDataCount = cpu_to_le16(4100); | 4638 | pSMB->MaxDataCount = cpu_to_le16(4100); |
4618 | pSMB->MaxSetupCount = 0; | 4639 | pSMB->MaxSetupCount = 0; |
@@ -4675,11 +4696,9 @@ CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size, | |||
4675 | __u16 fid, __u32 pid_of_opener, int SetAllocation) | 4696 | __u16 fid, __u32 pid_of_opener, int SetAllocation) |
4676 | { | 4697 | { |
4677 | struct smb_com_transaction2_sfi_req *pSMB = NULL; | 4698 | struct smb_com_transaction2_sfi_req *pSMB = NULL; |
4678 | struct smb_com_transaction2_sfi_rsp *pSMBr = NULL; | ||
4679 | char *data_offset; | 4699 | char *data_offset; |
4680 | struct file_end_of_file_info *parm_data; | 4700 | struct file_end_of_file_info *parm_data; |
4681 | int rc = 0; | 4701 | int rc = 0; |
4682 | int bytes_returned = 0; | ||
4683 | __u16 params, param_offset, offset, byte_count, count; | 4702 | __u16 params, param_offset, offset, byte_count, count; |
4684 | 4703 | ||
4685 | cFYI(1, ("SetFileSize (via SetFileInfo) %lld", | 4704 | cFYI(1, ("SetFileSize (via SetFileInfo) %lld", |
@@ -4689,8 +4708,6 @@ CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size, | |||
4689 | if (rc) | 4708 | if (rc) |
4690 | return rc; | 4709 | return rc; |
4691 | 4710 | ||
4692 | pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB; | ||
4693 | |||
4694 | pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener); | 4711 | pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener); |
4695 | pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16)); | 4712 | pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16)); |
4696 | 4713 | ||
@@ -4741,17 +4758,13 @@ CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size, | |||
4741 | pSMB->Reserved4 = 0; | 4758 | pSMB->Reserved4 = 0; |
4742 | pSMB->hdr.smb_buf_length += byte_count; | 4759 | pSMB->hdr.smb_buf_length += byte_count; |
4743 | pSMB->ByteCount = cpu_to_le16(byte_count); | 4760 | pSMB->ByteCount = cpu_to_le16(byte_count); |
4744 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 4761 | rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); |
4745 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | ||
4746 | if (rc) { | 4762 | if (rc) { |
4747 | cFYI(1, | 4763 | cFYI(1, |
4748 | ("Send error in SetFileInfo (SetFileSize) = %d", | 4764 | ("Send error in SetFileInfo (SetFileSize) = %d", |
4749 | rc)); | 4765 | rc)); |
4750 | } | 4766 | } |
4751 | 4767 | ||
4752 | if (pSMB) | ||
4753 | cifs_small_buf_release(pSMB); | ||
4754 | |||
4755 | /* Note: On -EAGAIN error only caller can retry on handle based calls | 4768 | /* Note: On -EAGAIN error only caller can retry on handle based calls |
4756 | since file handle passed in no longer valid */ | 4769 | since file handle passed in no longer valid */ |
4757 | 4770 | ||
@@ -4769,10 +4782,8 @@ CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon, | |||
4769 | const FILE_BASIC_INFO *data, __u16 fid) | 4782 | const FILE_BASIC_INFO *data, __u16 fid) |
4770 | { | 4783 | { |
4771 | struct smb_com_transaction2_sfi_req *pSMB = NULL; | 4784 | struct smb_com_transaction2_sfi_req *pSMB = NULL; |
4772 | struct smb_com_transaction2_sfi_rsp *pSMBr = NULL; | ||
4773 | char *data_offset; | 4785 | char *data_offset; |
4774 | int rc = 0; | 4786 | int rc = 0; |
4775 | int bytes_returned = 0; | ||
4776 | __u16 params, param_offset, offset, byte_count, count; | 4787 | __u16 params, param_offset, offset, byte_count, count; |
4777 | 4788 | ||
4778 | cFYI(1, ("Set Times (via SetFileInfo)")); | 4789 | cFYI(1, ("Set Times (via SetFileInfo)")); |
@@ -4781,8 +4792,6 @@ CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon, | |||
4781 | if (rc) | 4792 | if (rc) |
4782 | return rc; | 4793 | return rc; |
4783 | 4794 | ||
4784 | pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB; | ||
4785 | |||
4786 | /* At this point there is no need to override the current pid | 4795 | /* At this point there is no need to override the current pid |
4787 | with the pid of the opener, but that could change if we someday | 4796 | with the pid of the opener, but that could change if we someday |
4788 | use an existing handle (rather than opening one on the fly) */ | 4797 | use an existing handle (rather than opening one on the fly) */ |
@@ -4800,7 +4809,7 @@ CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon, | |||
4800 | 4809 | ||
4801 | data_offset = (char *) (&pSMB->hdr.Protocol) + offset; | 4810 | data_offset = (char *) (&pSMB->hdr.Protocol) + offset; |
4802 | 4811 | ||
4803 | count = sizeof (FILE_BASIC_INFO); | 4812 | count = sizeof(FILE_BASIC_INFO); |
4804 | pSMB->MaxParameterCount = cpu_to_le16(2); | 4813 | pSMB->MaxParameterCount = cpu_to_le16(2); |
4805 | pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */ | 4814 | pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */ |
4806 | pSMB->SetupCount = 1; | 4815 | pSMB->SetupCount = 1; |
@@ -4822,14 +4831,11 @@ CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon, | |||
4822 | pSMB->hdr.smb_buf_length += byte_count; | 4831 | pSMB->hdr.smb_buf_length += byte_count; |
4823 | pSMB->ByteCount = cpu_to_le16(byte_count); | 4832 | pSMB->ByteCount = cpu_to_le16(byte_count); |
4824 | memcpy(data_offset, data, sizeof(FILE_BASIC_INFO)); | 4833 | memcpy(data_offset, data, sizeof(FILE_BASIC_INFO)); |
4825 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 4834 | rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); |
4826 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | ||
4827 | if (rc) { | 4835 | if (rc) { |
4828 | cFYI(1, ("Send error in Set Time (SetFileInfo) = %d", rc)); | 4836 | cFYI(1, ("Send error in Set Time (SetFileInfo) = %d", rc)); |
4829 | } | 4837 | } |
4830 | 4838 | ||
4831 | cifs_small_buf_release(pSMB); | ||
4832 | |||
4833 | /* Note: On -EAGAIN error only caller can retry on handle based calls | 4839 | /* Note: On -EAGAIN error only caller can retry on handle based calls |
4834 | since file handle passed in no longer valid */ | 4840 | since file handle passed in no longer valid */ |
4835 | 4841 | ||
@@ -4871,7 +4877,7 @@ SetTimesRetry: | |||
4871 | } | 4877 | } |
4872 | 4878 | ||
4873 | params = 6 + name_len; | 4879 | params = 6 + name_len; |
4874 | count = sizeof (FILE_BASIC_INFO); | 4880 | count = sizeof(FILE_BASIC_INFO); |
4875 | pSMB->MaxParameterCount = cpu_to_le16(2); | 4881 | pSMB->MaxParameterCount = cpu_to_le16(2); |
4876 | pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */ | 4882 | pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */ |
4877 | pSMB->MaxSetupCount = 0; | 4883 | pSMB->MaxSetupCount = 0; |
@@ -4900,7 +4906,7 @@ SetTimesRetry: | |||
4900 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO); | 4906 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO); |
4901 | pSMB->Reserved4 = 0; | 4907 | pSMB->Reserved4 = 0; |
4902 | pSMB->hdr.smb_buf_length += byte_count; | 4908 | pSMB->hdr.smb_buf_length += byte_count; |
4903 | memcpy(data_offset, data, sizeof (FILE_BASIC_INFO)); | 4909 | memcpy(data_offset, data, sizeof(FILE_BASIC_INFO)); |
4904 | pSMB->ByteCount = cpu_to_le16(byte_count); | 4910 | pSMB->ByteCount = cpu_to_le16(byte_count); |
4905 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 4911 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
4906 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 4912 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
@@ -5003,7 +5009,7 @@ setPermsRetry: | |||
5003 | } | 5009 | } |
5004 | 5010 | ||
5005 | params = 6 + name_len; | 5011 | params = 6 + name_len; |
5006 | count = sizeof (FILE_UNIX_BASIC_INFO); | 5012 | count = sizeof(FILE_UNIX_BASIC_INFO); |
5007 | pSMB->MaxParameterCount = cpu_to_le16(2); | 5013 | pSMB->MaxParameterCount = cpu_to_le16(2); |
5008 | pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */ | 5014 | pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */ |
5009 | pSMB->MaxSetupCount = 0; | 5015 | pSMB->MaxSetupCount = 0; |
@@ -5120,7 +5126,8 @@ int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon, | |||
5120 | pSMB->ByteCount = 0; | 5126 | pSMB->ByteCount = 0; |
5121 | 5127 | ||
5122 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 5128 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
5123 | (struct smb_hdr *) pSMBr, &bytes_returned, -1); | 5129 | (struct smb_hdr *)pSMBr, &bytes_returned, |
5130 | CIFS_ASYNC_OP); | ||
5124 | if (rc) { | 5131 | if (rc) { |
5125 | cFYI(1, ("Error in Notify = %d", rc)); | 5132 | cFYI(1, ("Error in Notify = %d", rc)); |
5126 | } else { | 5133 | } else { |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 4af3588c1a96..fd9147cdb5a9 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -124,7 +124,7 @@ cifs_reconnect(struct TCP_Server_Info *server) | |||
124 | struct mid_q_entry *mid_entry; | 124 | struct mid_q_entry *mid_entry; |
125 | 125 | ||
126 | spin_lock(&GlobalMid_Lock); | 126 | spin_lock(&GlobalMid_Lock); |
127 | if ( kthread_should_stop() ) { | 127 | if (kthread_should_stop()) { |
128 | /* the demux thread will exit normally | 128 | /* the demux thread will exit normally |
129 | next time through the loop */ | 129 | next time through the loop */ |
130 | spin_unlock(&GlobalMid_Lock); | 130 | spin_unlock(&GlobalMid_Lock); |
@@ -151,9 +151,8 @@ cifs_reconnect(struct TCP_Server_Info *server) | |||
151 | } | 151 | } |
152 | list_for_each(tmp, &GlobalTreeConnectionList) { | 152 | list_for_each(tmp, &GlobalTreeConnectionList) { |
153 | tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList); | 153 | tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList); |
154 | if ((tcon) && (tcon->ses) && (tcon->ses->server == server)) { | 154 | if ((tcon) && (tcon->ses) && (tcon->ses->server == server)) |
155 | tcon->tidStatus = CifsNeedReconnect; | 155 | tcon->tidStatus = CifsNeedReconnect; |
156 | } | ||
157 | } | 156 | } |
158 | read_unlock(&GlobalSMBSeslock); | 157 | read_unlock(&GlobalSMBSeslock); |
159 | /* do not want to be sending data on a socket we are freeing */ | 158 | /* do not want to be sending data on a socket we are freeing */ |
@@ -161,7 +160,7 @@ cifs_reconnect(struct TCP_Server_Info *server) | |||
161 | if (server->ssocket) { | 160 | if (server->ssocket) { |
162 | cFYI(1, ("State: 0x%x Flags: 0x%lx", server->ssocket->state, | 161 | cFYI(1, ("State: 0x%x Flags: 0x%lx", server->ssocket->state, |
163 | server->ssocket->flags)); | 162 | server->ssocket->flags)); |
164 | server->ssocket->ops->shutdown(server->ssocket, SEND_SHUTDOWN); | 163 | kernel_sock_shutdown(server->ssocket, SHUT_WR); |
165 | cFYI(1, ("Post shutdown state: 0x%x Flags: 0x%lx", | 164 | cFYI(1, ("Post shutdown state: 0x%x Flags: 0x%lx", |
166 | server->ssocket->state, | 165 | server->ssocket->state, |
167 | server->ssocket->flags)); | 166 | server->ssocket->flags)); |
@@ -187,7 +186,7 @@ cifs_reconnect(struct TCP_Server_Info *server) | |||
187 | spin_unlock(&GlobalMid_Lock); | 186 | spin_unlock(&GlobalMid_Lock); |
188 | up(&server->tcpSem); | 187 | up(&server->tcpSem); |
189 | 188 | ||
190 | while ( (!kthread_should_stop()) && (server->tcpStatus != CifsGood)) { | 189 | while ((!kthread_should_stop()) && (server->tcpStatus != CifsGood)) { |
191 | try_to_freeze(); | 190 | try_to_freeze(); |
192 | if (server->protocolType == IPV6) { | 191 | if (server->protocolType == IPV6) { |
193 | rc = ipv6_connect(&server->addr.sockAddr6, | 192 | rc = ipv6_connect(&server->addr.sockAddr6, |
@@ -204,7 +203,7 @@ cifs_reconnect(struct TCP_Server_Info *server) | |||
204 | } else { | 203 | } else { |
205 | atomic_inc(&tcpSesReconnectCount); | 204 | atomic_inc(&tcpSesReconnectCount); |
206 | spin_lock(&GlobalMid_Lock); | 205 | spin_lock(&GlobalMid_Lock); |
207 | if ( !kthread_should_stop() ) | 206 | if (!kthread_should_stop()) |
208 | server->tcpStatus = CifsGood; | 207 | server->tcpStatus = CifsGood; |
209 | server->sequence_number = 0; | 208 | server->sequence_number = 0; |
210 | spin_unlock(&GlobalMid_Lock); | 209 | spin_unlock(&GlobalMid_Lock); |
@@ -352,17 +351,15 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) | |||
352 | 351 | ||
353 | current->flags |= PF_MEMALLOC; | 352 | current->flags |= PF_MEMALLOC; |
354 | server->tsk = current; /* save process info to wake at shutdown */ | 353 | server->tsk = current; /* save process info to wake at shutdown */ |
355 | cFYI(1, ("Demultiplex PID: %d", current->pid)); | 354 | cFYI(1, ("Demultiplex PID: %d", task_pid_nr(current))); |
356 | write_lock(&GlobalSMBSeslock); | 355 | write_lock(&GlobalSMBSeslock); |
357 | atomic_inc(&tcpSesAllocCount); | 356 | atomic_inc(&tcpSesAllocCount); |
358 | length = tcpSesAllocCount.counter; | 357 | length = tcpSesAllocCount.counter; |
359 | write_unlock(&GlobalSMBSeslock); | 358 | write_unlock(&GlobalSMBSeslock); |
360 | complete(&cifsd_complete); | 359 | complete(&cifsd_complete); |
361 | if (length > 1) { | 360 | if (length > 1) |
362 | mempool_resize(cifs_req_poolp, | 361 | mempool_resize(cifs_req_poolp, length + cifs_min_rcv, |
363 | length + cifs_min_rcv, | 362 | GFP_KERNEL); |
364 | GFP_KERNEL); | ||
365 | } | ||
366 | 363 | ||
367 | set_freezable(); | 364 | set_freezable(); |
368 | while (!kthread_should_stop()) { | 365 | while (!kthread_should_stop()) { |
@@ -378,7 +375,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) | |||
378 | } | 375 | } |
379 | } else if (isLargeBuf) { | 376 | } else if (isLargeBuf) { |
380 | /* we are reusing a dirty large buf, clear its start */ | 377 | /* we are reusing a dirty large buf, clear its start */ |
381 | memset(bigbuf, 0, sizeof (struct smb_hdr)); | 378 | memset(bigbuf, 0, sizeof(struct smb_hdr)); |
382 | } | 379 | } |
383 | 380 | ||
384 | if (smallbuf == NULL) { | 381 | if (smallbuf == NULL) { |
@@ -391,7 +388,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) | |||
391 | } | 388 | } |
392 | /* beginning of smb buffer is cleared in our buf_get */ | 389 | /* beginning of smb buffer is cleared in our buf_get */ |
393 | } else /* if existing small buf clear beginning */ | 390 | } else /* if existing small buf clear beginning */ |
394 | memset(smallbuf, 0, sizeof (struct smb_hdr)); | 391 | memset(smallbuf, 0, sizeof(struct smb_hdr)); |
395 | 392 | ||
396 | isLargeBuf = FALSE; | 393 | isLargeBuf = FALSE; |
397 | isMultiRsp = FALSE; | 394 | isMultiRsp = FALSE; |
@@ -400,11 +397,13 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) | |||
400 | iov.iov_len = 4; | 397 | iov.iov_len = 4; |
401 | smb_msg.msg_control = NULL; | 398 | smb_msg.msg_control = NULL; |
402 | smb_msg.msg_controllen = 0; | 399 | smb_msg.msg_controllen = 0; |
400 | pdu_length = 4; /* enough to get RFC1001 header */ | ||
401 | incomplete_rcv: | ||
403 | length = | 402 | length = |
404 | kernel_recvmsg(csocket, &smb_msg, | 403 | kernel_recvmsg(csocket, &smb_msg, |
405 | &iov, 1, 4, 0 /* BB see socket.h flags */); | 404 | &iov, 1, pdu_length, 0 /* BB other flags? */); |
406 | 405 | ||
407 | if ( kthread_should_stop() ) { | 406 | if (kthread_should_stop()) { |
408 | break; | 407 | break; |
409 | } else if (server->tcpStatus == CifsNeedReconnect) { | 408 | } else if (server->tcpStatus == CifsNeedReconnect) { |
410 | cFYI(1, ("Reconnect after server stopped responding")); | 409 | cFYI(1, ("Reconnect after server stopped responding")); |
@@ -416,7 +415,10 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) | |||
416 | msleep(1); /* minimum sleep to prevent looping | 415 | msleep(1); /* minimum sleep to prevent looping |
417 | allowing socket to clear and app threads to set | 416 | allowing socket to clear and app threads to set |
418 | tcpStatus CifsNeedReconnect if server hung */ | 417 | tcpStatus CifsNeedReconnect if server hung */ |
419 | continue; | 418 | if (pdu_length < 4) |
419 | goto incomplete_rcv; | ||
420 | else | ||
421 | continue; | ||
420 | } else if (length <= 0) { | 422 | } else if (length <= 0) { |
421 | if (server->tcpStatus == CifsNew) { | 423 | if (server->tcpStatus == CifsNew) { |
422 | cFYI(1, ("tcp session abend after SMBnegprot")); | 424 | cFYI(1, ("tcp session abend after SMBnegprot")); |
@@ -436,14 +438,12 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) | |||
436 | csocket = server->ssocket; | 438 | csocket = server->ssocket; |
437 | wake_up(&server->response_q); | 439 | wake_up(&server->response_q); |
438 | continue; | 440 | continue; |
439 | } else if (length < 4) { | 441 | } else if (length < pdu_length) { |
440 | cFYI(1, | 442 | cFYI(1, ("requested %d bytes but only got %d bytes", |
441 | ("Frame under four bytes received (%d bytes long)", | 443 | pdu_length, length)); |
442 | length)); | 444 | pdu_length -= length; |
443 | cifs_reconnect(server); | 445 | msleep(1); |
444 | csocket = server->ssocket; | 446 | goto incomplete_rcv; |
445 | wake_up(&server->response_q); | ||
446 | continue; | ||
447 | } | 447 | } |
448 | 448 | ||
449 | /* The right amount was read from socket - 4 bytes */ | 449 | /* The right amount was read from socket - 4 bytes */ |
@@ -504,7 +504,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) | |||
504 | 504 | ||
505 | /* else we have an SMB response */ | 505 | /* else we have an SMB response */ |
506 | if ((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) || | 506 | if ((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) || |
507 | (pdu_length < sizeof (struct smb_hdr) - 1 - 4)) { | 507 | (pdu_length < sizeof(struct smb_hdr) - 1 - 4)) { |
508 | cERROR(1, ("Invalid size SMB length %d pdu_length %d", | 508 | cERROR(1, ("Invalid size SMB length %d pdu_length %d", |
509 | length, pdu_length+4)); | 509 | length, pdu_length+4)); |
510 | cifs_reconnect(server); | 510 | cifs_reconnect(server); |
@@ -528,7 +528,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) | |||
528 | total_read += length) { | 528 | total_read += length) { |
529 | length = kernel_recvmsg(csocket, &smb_msg, &iov, 1, | 529 | length = kernel_recvmsg(csocket, &smb_msg, &iov, 1, |
530 | pdu_length - total_read, 0); | 530 | pdu_length - total_read, 0); |
531 | if ( kthread_should_stop() || | 531 | if (kthread_should_stop() || |
532 | (length == -EINTR)) { | 532 | (length == -EINTR)) { |
533 | /* then will exit */ | 533 | /* then will exit */ |
534 | reconnect = 2; | 534 | reconnect = 2; |
@@ -546,6 +546,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) | |||
546 | allowing socket to clear and app | 546 | allowing socket to clear and app |
547 | threads to set tcpStatus | 547 | threads to set tcpStatus |
548 | CifsNeedReconnect if server hung*/ | 548 | CifsNeedReconnect if server hung*/ |
549 | length = 0; | ||
549 | continue; | 550 | continue; |
550 | } else if (length <= 0) { | 551 | } else if (length <= 0) { |
551 | cERROR(1, ("Received no data, expecting %d", | 552 | cERROR(1, ("Received no data, expecting %d", |
@@ -631,9 +632,9 @@ multi_t2_fnd: | |||
631 | /* Was previous buf put in mpx struct for multi-rsp? */ | 632 | /* Was previous buf put in mpx struct for multi-rsp? */ |
632 | if (!isMultiRsp) { | 633 | if (!isMultiRsp) { |
633 | /* smb buffer will be freed by user thread */ | 634 | /* smb buffer will be freed by user thread */ |
634 | if (isLargeBuf) { | 635 | if (isLargeBuf) |
635 | bigbuf = NULL; | 636 | bigbuf = NULL; |
636 | } else | 637 | else |
637 | smallbuf = NULL; | 638 | smallbuf = NULL; |
638 | } | 639 | } |
639 | wake_up_process(task_to_wake); | 640 | wake_up_process(task_to_wake); |
@@ -676,9 +677,8 @@ multi_t2_fnd: | |||
676 | server->ssocket = NULL; | 677 | server->ssocket = NULL; |
677 | } | 678 | } |
678 | /* buffer usuallly freed in free_mid - need to free it here on exit */ | 679 | /* buffer usuallly freed in free_mid - need to free it here on exit */ |
679 | if (bigbuf != NULL) | 680 | cifs_buf_release(bigbuf); |
680 | cifs_buf_release(bigbuf); | 681 | if (smallbuf) /* no sense logging a debug message if NULL */ |
681 | if (smallbuf != NULL) | ||
682 | cifs_small_buf_release(smallbuf); | 682 | cifs_small_buf_release(smallbuf); |
683 | 683 | ||
684 | read_lock(&GlobalSMBSeslock); | 684 | read_lock(&GlobalSMBSeslock); |
@@ -702,9 +702,8 @@ multi_t2_fnd: | |||
702 | list_for_each(tmp, &GlobalSMBSessionList) { | 702 | list_for_each(tmp, &GlobalSMBSessionList) { |
703 | ses = list_entry(tmp, struct cifsSesInfo, | 703 | ses = list_entry(tmp, struct cifsSesInfo, |
704 | cifsSessionList); | 704 | cifsSessionList); |
705 | if (ses->server == server) { | 705 | if (ses->server == server) |
706 | ses->status = CifsExiting; | 706 | ses->status = CifsExiting; |
707 | } | ||
708 | } | 707 | } |
709 | 708 | ||
710 | spin_lock(&GlobalMid_Lock); | 709 | spin_lock(&GlobalMid_Lock); |
@@ -714,9 +713,8 @@ multi_t2_fnd: | |||
714 | cFYI(1, ("Clearing Mid 0x%x - waking up ", | 713 | cFYI(1, ("Clearing Mid 0x%x - waking up ", |
715 | mid_entry->mid)); | 714 | mid_entry->mid)); |
716 | task_to_wake = mid_entry->tsk; | 715 | task_to_wake = mid_entry->tsk; |
717 | if (task_to_wake) { | 716 | if (task_to_wake) |
718 | wake_up_process(task_to_wake); | 717 | wake_up_process(task_to_wake); |
719 | } | ||
720 | } | 718 | } |
721 | } | 719 | } |
722 | spin_unlock(&GlobalMid_Lock); | 720 | spin_unlock(&GlobalMid_Lock); |
@@ -749,22 +747,48 @@ multi_t2_fnd: | |||
749 | list_for_each(tmp, &GlobalSMBSessionList) { | 747 | list_for_each(tmp, &GlobalSMBSessionList) { |
750 | ses = list_entry(tmp, struct cifsSesInfo, | 748 | ses = list_entry(tmp, struct cifsSesInfo, |
751 | cifsSessionList); | 749 | cifsSessionList); |
752 | if (ses->server == server) { | 750 | if (ses->server == server) |
753 | ses->server = NULL; | 751 | ses->server = NULL; |
754 | } | ||
755 | } | 752 | } |
756 | write_unlock(&GlobalSMBSeslock); | 753 | write_unlock(&GlobalSMBSeslock); |
757 | 754 | ||
755 | kfree(server->hostname); | ||
758 | kfree(server); | 756 | kfree(server); |
759 | if (length > 0) { | 757 | if (length > 0) |
760 | mempool_resize(cifs_req_poolp, | 758 | mempool_resize(cifs_req_poolp, length + cifs_min_rcv, |
761 | length + cifs_min_rcv, | 759 | GFP_KERNEL); |
762 | GFP_KERNEL); | ||
763 | } | ||
764 | 760 | ||
765 | return 0; | 761 | return 0; |
766 | } | 762 | } |
767 | 763 | ||
764 | /* extract the host portion of the UNC string */ | ||
765 | static char * | ||
766 | extract_hostname(const char *unc) | ||
767 | { | ||
768 | const char *src; | ||
769 | char *dst, *delim; | ||
770 | unsigned int len; | ||
771 | |||
772 | /* skip double chars at beginning of string */ | ||
773 | /* BB: check validity of these bytes? */ | ||
774 | src = unc + 2; | ||
775 | |||
776 | /* delimiter between hostname and sharename is always '\\' now */ | ||
777 | delim = strchr(src, '\\'); | ||
778 | if (!delim) | ||
779 | return ERR_PTR(-EINVAL); | ||
780 | |||
781 | len = delim - src; | ||
782 | dst = kmalloc((len + 1), GFP_KERNEL); | ||
783 | if (dst == NULL) | ||
784 | return ERR_PTR(-ENOMEM); | ||
785 | |||
786 | memcpy(dst, src, len); | ||
787 | dst[len] = '\0'; | ||
788 | |||
789 | return dst; | ||
790 | } | ||
791 | |||
768 | static int | 792 | static int |
769 | cifs_parse_mount_options(char *options, const char *devname, | 793 | cifs_parse_mount_options(char *options, const char *devname, |
770 | struct smb_vol *vol) | 794 | struct smb_vol *vol) |
@@ -798,7 +822,7 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
798 | vol->linux_gid = current->gid; | 822 | vol->linux_gid = current->gid; |
799 | vol->dir_mode = S_IRWXUGO; | 823 | vol->dir_mode = S_IRWXUGO; |
800 | /* 2767 perms indicate mandatory locking support */ | 824 | /* 2767 perms indicate mandatory locking support */ |
801 | vol->file_mode = S_IALLUGO & ~(S_ISUID | S_IXGRP); | 825 | vol->file_mode = (S_IRWXUGO | S_ISGID) & (~S_IXGRP); |
802 | 826 | ||
803 | /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */ | 827 | /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */ |
804 | vol->rw = TRUE; | 828 | vol->rw = TRUE; |
@@ -1477,7 +1501,7 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket, | |||
1477 | if (psin_server->sin_port) { /* user overrode default port */ | 1501 | if (psin_server->sin_port) { /* user overrode default port */ |
1478 | rc = (*csocket)->ops->connect(*csocket, | 1502 | rc = (*csocket)->ops->connect(*csocket, |
1479 | (struct sockaddr *) psin_server, | 1503 | (struct sockaddr *) psin_server, |
1480 | sizeof (struct sockaddr_in), 0); | 1504 | sizeof(struct sockaddr_in), 0); |
1481 | if (rc >= 0) | 1505 | if (rc >= 0) |
1482 | connected = 1; | 1506 | connected = 1; |
1483 | } | 1507 | } |
@@ -1493,7 +1517,7 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket, | |||
1493 | 1517 | ||
1494 | rc = (*csocket)->ops->connect(*csocket, | 1518 | rc = (*csocket)->ops->connect(*csocket, |
1495 | (struct sockaddr *) psin_server, | 1519 | (struct sockaddr *) psin_server, |
1496 | sizeof (struct sockaddr_in), 0); | 1520 | sizeof(struct sockaddr_in), 0); |
1497 | if (rc >= 0) | 1521 | if (rc >= 0) |
1498 | connected = 1; | 1522 | connected = 1; |
1499 | } | 1523 | } |
@@ -1502,7 +1526,7 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket, | |||
1502 | psin_server->sin_port = htons(RFC1001_PORT); | 1526 | psin_server->sin_port = htons(RFC1001_PORT); |
1503 | rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *) | 1527 | rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *) |
1504 | psin_server, | 1528 | psin_server, |
1505 | sizeof (struct sockaddr_in), 0); | 1529 | sizeof(struct sockaddr_in), 0); |
1506 | if (rc >= 0) | 1530 | if (rc >= 0) |
1507 | connected = 1; | 1531 | connected = 1; |
1508 | } | 1532 | } |
@@ -1610,7 +1634,7 @@ ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket) | |||
1610 | if (psin_server->sin6_port) { /* user overrode default port */ | 1634 | if (psin_server->sin6_port) { /* user overrode default port */ |
1611 | rc = (*csocket)->ops->connect(*csocket, | 1635 | rc = (*csocket)->ops->connect(*csocket, |
1612 | (struct sockaddr *) psin_server, | 1636 | (struct sockaddr *) psin_server, |
1613 | sizeof (struct sockaddr_in6), 0); | 1637 | sizeof(struct sockaddr_in6), 0); |
1614 | if (rc >= 0) | 1638 | if (rc >= 0) |
1615 | connected = 1; | 1639 | connected = 1; |
1616 | } | 1640 | } |
@@ -1626,7 +1650,7 @@ ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket) | |||
1626 | 1650 | ||
1627 | rc = (*csocket)->ops->connect(*csocket, | 1651 | rc = (*csocket)->ops->connect(*csocket, |
1628 | (struct sockaddr *) psin_server, | 1652 | (struct sockaddr *) psin_server, |
1629 | sizeof (struct sockaddr_in6), 0); | 1653 | sizeof(struct sockaddr_in6), 0); |
1630 | if (rc >= 0) | 1654 | if (rc >= 0) |
1631 | connected = 1; | 1655 | connected = 1; |
1632 | } | 1656 | } |
@@ -1634,7 +1658,7 @@ ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket) | |||
1634 | if (!connected) { | 1658 | if (!connected) { |
1635 | psin_server->sin6_port = htons(RFC1001_PORT); | 1659 | psin_server->sin6_port = htons(RFC1001_PORT); |
1636 | rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *) | 1660 | rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *) |
1637 | psin_server, sizeof (struct sockaddr_in6), 0); | 1661 | psin_server, sizeof(struct sockaddr_in6), 0); |
1638 | if (rc >= 0) | 1662 | if (rc >= 0) |
1639 | connected = 1; | 1663 | connected = 1; |
1640 | } | 1664 | } |
@@ -1750,7 +1774,16 @@ void reset_cifs_unix_caps(int xid, struct cifsTconInfo *tcon, | |||
1750 | cFYI(1, ("very large write cap")); | 1774 | cFYI(1, ("very large write cap")); |
1751 | #endif /* CIFS_DEBUG2 */ | 1775 | #endif /* CIFS_DEBUG2 */ |
1752 | if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) { | 1776 | if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) { |
1753 | cFYI(1, ("setting capabilities failed")); | 1777 | if (vol_info == NULL) { |
1778 | cFYI(1, ("resetting capabilities failed")); | ||
1779 | } else | ||
1780 | cERROR(1, ("Negotiating Unix capabilities " | ||
1781 | "with the server failed. Consider " | ||
1782 | "mounting with the Unix Extensions\n" | ||
1783 | "disabled, if problems are found, " | ||
1784 | "by specifying the nounix mount " | ||
1785 | "option.")); | ||
1786 | |||
1754 | } | 1787 | } |
1755 | } | 1788 | } |
1756 | } | 1789 | } |
@@ -1777,16 +1810,13 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1777 | 1810 | ||
1778 | memset(&volume_info, 0, sizeof(struct smb_vol)); | 1811 | memset(&volume_info, 0, sizeof(struct smb_vol)); |
1779 | if (cifs_parse_mount_options(mount_data, devname, &volume_info)) { | 1812 | if (cifs_parse_mount_options(mount_data, devname, &volume_info)) { |
1780 | kfree(volume_info.UNC); | 1813 | rc = -EINVAL; |
1781 | kfree(volume_info.password); | 1814 | goto out; |
1782 | kfree(volume_info.prepath); | ||
1783 | FreeXid(xid); | ||
1784 | return -EINVAL; | ||
1785 | } | 1815 | } |
1786 | 1816 | ||
1787 | if (volume_info.nullauth) { | 1817 | if (volume_info.nullauth) { |
1788 | cFYI(1, ("null user")); | 1818 | cFYI(1, ("null user")); |
1789 | volume_info.username = NULL; | 1819 | volume_info.username = ""; |
1790 | } else if (volume_info.username) { | 1820 | } else if (volume_info.username) { |
1791 | /* BB fixme parse for domain name here */ | 1821 | /* BB fixme parse for domain name here */ |
1792 | cFYI(1, ("Username: %s", volume_info.username)); | 1822 | cFYI(1, ("Username: %s", volume_info.username)); |
@@ -1794,11 +1824,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1794 | cifserror("No username specified"); | 1824 | cifserror("No username specified"); |
1795 | /* In userspace mount helper we can get user name from alternate | 1825 | /* In userspace mount helper we can get user name from alternate |
1796 | locations such as env variables and files on disk */ | 1826 | locations such as env variables and files on disk */ |
1797 | kfree(volume_info.UNC); | 1827 | rc = -EINVAL; |
1798 | kfree(volume_info.password); | 1828 | goto out; |
1799 | kfree(volume_info.prepath); | ||
1800 | FreeXid(xid); | ||
1801 | return -EINVAL; | ||
1802 | } | 1829 | } |
1803 | 1830 | ||
1804 | if (volume_info.UNCip && volume_info.UNC) { | 1831 | if (volume_info.UNCip && volume_info.UNC) { |
@@ -1817,11 +1844,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1817 | 1844 | ||
1818 | if (rc <= 0) { | 1845 | if (rc <= 0) { |
1819 | /* we failed translating address */ | 1846 | /* we failed translating address */ |
1820 | kfree(volume_info.UNC); | 1847 | rc = -EINVAL; |
1821 | kfree(volume_info.password); | 1848 | goto out; |
1822 | kfree(volume_info.prepath); | ||
1823 | FreeXid(xid); | ||
1824 | return -EINVAL; | ||
1825 | } | 1849 | } |
1826 | 1850 | ||
1827 | cFYI(1, ("UNC: %s ip: %s", volume_info.UNC, volume_info.UNCip)); | 1851 | cFYI(1, ("UNC: %s ip: %s", volume_info.UNC, volume_info.UNCip)); |
@@ -1831,20 +1855,14 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1831 | /* BB using ip addr as server name to connect to the | 1855 | /* BB using ip addr as server name to connect to the |
1832 | DFS root below */ | 1856 | DFS root below */ |
1833 | cERROR(1, ("Connecting to DFS root not implemented yet")); | 1857 | cERROR(1, ("Connecting to DFS root not implemented yet")); |
1834 | kfree(volume_info.UNC); | 1858 | rc = -EINVAL; |
1835 | kfree(volume_info.password); | 1859 | goto out; |
1836 | kfree(volume_info.prepath); | ||
1837 | FreeXid(xid); | ||
1838 | return -EINVAL; | ||
1839 | } else /* which servers DFS root would we conect to */ { | 1860 | } else /* which servers DFS root would we conect to */ { |
1840 | cERROR(1, | 1861 | cERROR(1, |
1841 | ("CIFS mount error: No UNC path (e.g. -o " | 1862 | ("CIFS mount error: No UNC path (e.g. -o " |
1842 | "unc=//192.168.1.100/public) specified")); | 1863 | "unc=//192.168.1.100/public) specified")); |
1843 | kfree(volume_info.UNC); | 1864 | rc = -EINVAL; |
1844 | kfree(volume_info.password); | 1865 | goto out; |
1845 | kfree(volume_info.prepath); | ||
1846 | FreeXid(xid); | ||
1847 | return -EINVAL; | ||
1848 | } | 1866 | } |
1849 | 1867 | ||
1850 | /* this is needed for ASCII cp to Unicode converts */ | 1868 | /* this is needed for ASCII cp to Unicode converts */ |
@@ -1856,11 +1874,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1856 | if (cifs_sb->local_nls == NULL) { | 1874 | if (cifs_sb->local_nls == NULL) { |
1857 | cERROR(1, ("CIFS mount error: iocharset %s not found", | 1875 | cERROR(1, ("CIFS mount error: iocharset %s not found", |
1858 | volume_info.iocharset)); | 1876 | volume_info.iocharset)); |
1859 | kfree(volume_info.UNC); | 1877 | rc = -ELIBACC; |
1860 | kfree(volume_info.password); | 1878 | goto out; |
1861 | kfree(volume_info.prepath); | ||
1862 | FreeXid(xid); | ||
1863 | return -ELIBACC; | ||
1864 | } | 1879 | } |
1865 | } | 1880 | } |
1866 | 1881 | ||
@@ -1874,11 +1889,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1874 | &sin_server6.sin6_addr, | 1889 | &sin_server6.sin6_addr, |
1875 | volume_info.username, &srvTcp); | 1890 | volume_info.username, &srvTcp); |
1876 | } else { | 1891 | } else { |
1877 | kfree(volume_info.UNC); | 1892 | rc = -EINVAL; |
1878 | kfree(volume_info.password); | 1893 | goto out; |
1879 | kfree(volume_info.prepath); | ||
1880 | FreeXid(xid); | ||
1881 | return -EINVAL; | ||
1882 | } | 1894 | } |
1883 | 1895 | ||
1884 | if (srvTcp) { | 1896 | if (srvTcp) { |
@@ -1902,30 +1914,27 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1902 | "Aborting operation")); | 1914 | "Aborting operation")); |
1903 | if (csocket != NULL) | 1915 | if (csocket != NULL) |
1904 | sock_release(csocket); | 1916 | sock_release(csocket); |
1905 | kfree(volume_info.UNC); | 1917 | goto out; |
1906 | kfree(volume_info.password); | ||
1907 | kfree(volume_info.prepath); | ||
1908 | FreeXid(xid); | ||
1909 | return rc; | ||
1910 | } | 1918 | } |
1911 | 1919 | ||
1912 | srvTcp = kmalloc(sizeof (struct TCP_Server_Info), GFP_KERNEL); | 1920 | srvTcp = kzalloc(sizeof(struct TCP_Server_Info), GFP_KERNEL); |
1913 | if (srvTcp == NULL) { | 1921 | if (!srvTcp) { |
1914 | rc = -ENOMEM; | 1922 | rc = -ENOMEM; |
1915 | sock_release(csocket); | 1923 | sock_release(csocket); |
1916 | kfree(volume_info.UNC); | 1924 | goto out; |
1917 | kfree(volume_info.password); | ||
1918 | kfree(volume_info.prepath); | ||
1919 | FreeXid(xid); | ||
1920 | return rc; | ||
1921 | } else { | 1925 | } else { |
1922 | memset(srvTcp, 0, sizeof (struct TCP_Server_Info)); | ||
1923 | memcpy(&srvTcp->addr.sockAddr, &sin_server, | 1926 | memcpy(&srvTcp->addr.sockAddr, &sin_server, |
1924 | sizeof (struct sockaddr_in)); | 1927 | sizeof(struct sockaddr_in)); |
1925 | atomic_set(&srvTcp->inFlight, 0); | 1928 | atomic_set(&srvTcp->inFlight, 0); |
1926 | /* BB Add code for ipv6 case too */ | 1929 | /* BB Add code for ipv6 case too */ |
1927 | srvTcp->ssocket = csocket; | 1930 | srvTcp->ssocket = csocket; |
1928 | srvTcp->protocolType = IPV4; | 1931 | srvTcp->protocolType = IPV4; |
1932 | srvTcp->hostname = extract_hostname(volume_info.UNC); | ||
1933 | if (IS_ERR(srvTcp->hostname)) { | ||
1934 | rc = PTR_ERR(srvTcp->hostname); | ||
1935 | sock_release(csocket); | ||
1936 | goto out; | ||
1937 | } | ||
1929 | init_waitqueue_head(&srvTcp->response_q); | 1938 | init_waitqueue_head(&srvTcp->response_q); |
1930 | init_waitqueue_head(&srvTcp->request_q); | 1939 | init_waitqueue_head(&srvTcp->request_q); |
1931 | INIT_LIST_HEAD(&srvTcp->pending_mid_q); | 1940 | INIT_LIST_HEAD(&srvTcp->pending_mid_q); |
@@ -1935,16 +1944,13 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1935 | srvTcp->tcpStatus = CifsNew; | 1944 | srvTcp->tcpStatus = CifsNew; |
1936 | init_MUTEX(&srvTcp->tcpSem); | 1945 | init_MUTEX(&srvTcp->tcpSem); |
1937 | srvTcp->tsk = kthread_run((void *)(void *)cifs_demultiplex_thread, srvTcp, "cifsd"); | 1946 | srvTcp->tsk = kthread_run((void *)(void *)cifs_demultiplex_thread, srvTcp, "cifsd"); |
1938 | if ( IS_ERR(srvTcp->tsk) ) { | 1947 | if (IS_ERR(srvTcp->tsk)) { |
1939 | rc = PTR_ERR(srvTcp->tsk); | 1948 | rc = PTR_ERR(srvTcp->tsk); |
1940 | cERROR(1, ("error %d create cifsd thread", rc)); | 1949 | cERROR(1, ("error %d create cifsd thread", rc)); |
1941 | srvTcp->tsk = NULL; | 1950 | srvTcp->tsk = NULL; |
1942 | sock_release(csocket); | 1951 | sock_release(csocket); |
1943 | kfree(volume_info.UNC); | 1952 | kfree(srvTcp->hostname); |
1944 | kfree(volume_info.password); | 1953 | goto out; |
1945 | kfree(volume_info.prepath); | ||
1946 | FreeXid(xid); | ||
1947 | return rc; | ||
1948 | } | 1954 | } |
1949 | wait_for_completion(&cifsd_complete); | 1955 | wait_for_completion(&cifsd_complete); |
1950 | rc = 0; | 1956 | rc = 0; |
@@ -1959,8 +1965,6 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1959 | if (existingCifsSes) { | 1965 | if (existingCifsSes) { |
1960 | pSesInfo = existingCifsSes; | 1966 | pSesInfo = existingCifsSes; |
1961 | cFYI(1, ("Existing smb sess found")); | 1967 | cFYI(1, ("Existing smb sess found")); |
1962 | kfree(volume_info.password); | ||
1963 | /* volume_info.UNC freed at end of function */ | ||
1964 | } else if (!rc) { | 1968 | } else if (!rc) { |
1965 | cFYI(1, ("Existing smb sess not found")); | 1969 | cFYI(1, ("Existing smb sess not found")); |
1966 | pSesInfo = sesInfoAlloc(); | 1970 | pSesInfo = sesInfoAlloc(); |
@@ -1974,8 +1978,11 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1974 | 1978 | ||
1975 | if (!rc) { | 1979 | if (!rc) { |
1976 | /* volume_info.password freed at unmount */ | 1980 | /* volume_info.password freed at unmount */ |
1977 | if (volume_info.password) | 1981 | if (volume_info.password) { |
1978 | pSesInfo->password = volume_info.password; | 1982 | pSesInfo->password = volume_info.password; |
1983 | /* set to NULL to prevent freeing on exit */ | ||
1984 | volume_info.password = NULL; | ||
1985 | } | ||
1979 | if (volume_info.username) | 1986 | if (volume_info.username) |
1980 | strncpy(pSesInfo->userName, | 1987 | strncpy(pSesInfo->userName, |
1981 | volume_info.username, | 1988 | volume_info.username, |
@@ -1997,8 +2004,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1997 | up(&pSesInfo->sesSem); | 2004 | up(&pSesInfo->sesSem); |
1998 | if (!rc) | 2005 | if (!rc) |
1999 | atomic_inc(&srvTcp->socketUseCount); | 2006 | atomic_inc(&srvTcp->socketUseCount); |
2000 | } else | 2007 | } |
2001 | kfree(volume_info.password); | ||
2002 | } | 2008 | } |
2003 | 2009 | ||
2004 | /* search for existing tcon to this server share */ | 2010 | /* search for existing tcon to this server share */ |
@@ -2103,9 +2109,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
2103 | "", cifs_sb->local_nls, | 2109 | "", cifs_sb->local_nls, |
2104 | cifs_sb->mnt_cifs_flags & | 2110 | cifs_sb->mnt_cifs_flags & |
2105 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 2111 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
2106 | kfree(volume_info.UNC); | 2112 | rc = -ENODEV; |
2107 | FreeXid(xid); | 2113 | goto out; |
2108 | return -ENODEV; | ||
2109 | } else { | 2114 | } else { |
2110 | /* BB Do we need to wrap sesSem around | 2115 | /* BB Do we need to wrap sesSem around |
2111 | * this TCon call and Unix SetFS as | 2116 | * this TCon call and Unix SetFS as |
@@ -2173,8 +2178,18 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
2173 | if (tsk) | 2178 | if (tsk) |
2174 | kthread_stop(tsk); | 2179 | kthread_stop(tsk); |
2175 | } | 2180 | } |
2176 | } else | 2181 | } else { |
2177 | cFYI(1, ("No session or bad tcon")); | 2182 | cFYI(1, ("No session or bad tcon")); |
2183 | if ((pSesInfo->server) && | ||
2184 | (pSesInfo->server->tsk)) { | ||
2185 | struct task_struct *tsk; | ||
2186 | force_sig(SIGKILL, | ||
2187 | pSesInfo->server->tsk); | ||
2188 | tsk = pSesInfo->server->tsk; | ||
2189 | if (tsk) | ||
2190 | kthread_stop(tsk); | ||
2191 | } | ||
2192 | } | ||
2178 | sesInfoFree(pSesInfo); | 2193 | sesInfoFree(pSesInfo); |
2179 | /* pSesInfo = NULL; */ | 2194 | /* pSesInfo = NULL; */ |
2180 | } | 2195 | } |
@@ -2185,8 +2200,10 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
2185 | tcon->ses = pSesInfo; | 2200 | tcon->ses = pSesInfo; |
2186 | 2201 | ||
2187 | /* do not care if following two calls succeed - informational */ | 2202 | /* do not care if following two calls succeed - informational */ |
2188 | CIFSSMBQFSDeviceInfo(xid, tcon); | 2203 | if (!tcon->ipc) { |
2189 | CIFSSMBQFSAttributeInfo(xid, tcon); | 2204 | CIFSSMBQFSDeviceInfo(xid, tcon); |
2205 | CIFSSMBQFSAttributeInfo(xid, tcon); | ||
2206 | } | ||
2190 | 2207 | ||
2191 | /* tell server which Unix caps we support */ | 2208 | /* tell server which Unix caps we support */ |
2192 | if (tcon->ses->capabilities & CAP_UNIX) | 2209 | if (tcon->ses->capabilities & CAP_UNIX) |
@@ -2216,6 +2233,12 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
2216 | (in which case it is not needed anymore) but when new sesion is created | 2233 | (in which case it is not needed anymore) but when new sesion is created |
2217 | the password ptr is put in the new session structure (in which case the | 2234 | the password ptr is put in the new session structure (in which case the |
2218 | password will be freed at unmount time) */ | 2235 | password will be freed at unmount time) */ |
2236 | out: | ||
2237 | /* zero out password before freeing */ | ||
2238 | if (volume_info.password != NULL) { | ||
2239 | memset(volume_info.password, 0, strlen(volume_info.password)); | ||
2240 | kfree(volume_info.password); | ||
2241 | } | ||
2219 | kfree(volume_info.UNC); | 2242 | kfree(volume_info.UNC); |
2220 | kfree(volume_info.prepath); | 2243 | kfree(volume_info.prepath); |
2221 | FreeXid(xid); | 2244 | FreeXid(xid); |
@@ -2359,7 +2382,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
2359 | pSMB->req_no_secext.ByteCount = cpu_to_le16(count); | 2382 | pSMB->req_no_secext.ByteCount = cpu_to_le16(count); |
2360 | 2383 | ||
2361 | rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, | 2384 | rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, |
2362 | &bytes_returned, 1); | 2385 | &bytes_returned, CIFS_LONG_OP); |
2363 | if (rc) { | 2386 | if (rc) { |
2364 | /* rc = map_smb_to_linux_error(smb_buffer_response); now done in SendReceive */ | 2387 | /* rc = map_smb_to_linux_error(smb_buffer_response); now done in SendReceive */ |
2365 | } else if ((smb_buffer_response->WordCount == 3) | 2388 | } else if ((smb_buffer_response->WordCount == 3) |
@@ -2526,8 +2549,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
2526 | sesssetup_nomem: /* do not return an error on nomem for the info strings, | 2549 | sesssetup_nomem: /* do not return an error on nomem for the info strings, |
2527 | since that could make reconnection harder, and | 2550 | since that could make reconnection harder, and |
2528 | reconnection might be needed to free memory */ | 2551 | reconnection might be needed to free memory */ |
2529 | if (smb_buffer) | 2552 | cifs_buf_release(smb_buffer); |
2530 | cifs_buf_release(smb_buffer); | ||
2531 | 2553 | ||
2532 | return rc; | 2554 | return rc; |
2533 | } | 2555 | } |
@@ -2547,7 +2569,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, | |||
2547 | int remaining_words = 0; | 2569 | int remaining_words = 0; |
2548 | int bytes_returned = 0; | 2570 | int bytes_returned = 0; |
2549 | int len; | 2571 | int len; |
2550 | int SecurityBlobLength = sizeof (NEGOTIATE_MESSAGE); | 2572 | int SecurityBlobLength = sizeof(NEGOTIATE_MESSAGE); |
2551 | PNEGOTIATE_MESSAGE SecurityBlob; | 2573 | PNEGOTIATE_MESSAGE SecurityBlob; |
2552 | PCHALLENGE_MESSAGE SecurityBlob2; | 2574 | PCHALLENGE_MESSAGE SecurityBlob2; |
2553 | __u32 negotiate_flags, capabilities; | 2575 | __u32 negotiate_flags, capabilities; |
@@ -2664,7 +2686,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, | |||
2664 | pSMB->req.ByteCount = cpu_to_le16(count); | 2686 | pSMB->req.ByteCount = cpu_to_le16(count); |
2665 | 2687 | ||
2666 | rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, | 2688 | rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, |
2667 | &bytes_returned, 1); | 2689 | &bytes_returned, CIFS_LONG_OP); |
2668 | 2690 | ||
2669 | if (smb_buffer_response->Status.CifsError == | 2691 | if (smb_buffer_response->Status.CifsError == |
2670 | cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED)) | 2692 | cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED)) |
@@ -2865,15 +2887,14 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, | |||
2865 | rc = -EIO; | 2887 | rc = -EIO; |
2866 | } | 2888 | } |
2867 | 2889 | ||
2868 | if (smb_buffer) | 2890 | cifs_buf_release(smb_buffer); |
2869 | cifs_buf_release(smb_buffer); | ||
2870 | 2891 | ||
2871 | return rc; | 2892 | return rc; |
2872 | } | 2893 | } |
2873 | static int | 2894 | static int |
2874 | CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, | 2895 | CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, |
2875 | char *ntlm_session_key, int ntlmv2_flag, | 2896 | char *ntlm_session_key, int ntlmv2_flag, |
2876 | const struct nls_table *nls_codepage) | 2897 | const struct nls_table *nls_codepage) |
2877 | { | 2898 | { |
2878 | struct smb_hdr *smb_buffer; | 2899 | struct smb_hdr *smb_buffer; |
2879 | struct smb_hdr *smb_buffer_response; | 2900 | struct smb_hdr *smb_buffer_response; |
@@ -2886,7 +2907,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
2886 | int remaining_words = 0; | 2907 | int remaining_words = 0; |
2887 | int bytes_returned = 0; | 2908 | int bytes_returned = 0; |
2888 | int len; | 2909 | int len; |
2889 | int SecurityBlobLength = sizeof (AUTHENTICATE_MESSAGE); | 2910 | int SecurityBlobLength = sizeof(AUTHENTICATE_MESSAGE); |
2890 | PAUTHENTICATE_MESSAGE SecurityBlob; | 2911 | PAUTHENTICATE_MESSAGE SecurityBlob; |
2891 | __u32 negotiate_flags, capabilities; | 2912 | __u32 negotiate_flags, capabilities; |
2892 | __u16 count; | 2913 | __u16 count; |
@@ -2901,8 +2922,8 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
2901 | return -ENOMEM; | 2922 | return -ENOMEM; |
2902 | } | 2923 | } |
2903 | smb_buffer_response = smb_buffer; | 2924 | smb_buffer_response = smb_buffer; |
2904 | pSMB = (SESSION_SETUP_ANDX *) smb_buffer; | 2925 | pSMB = (SESSION_SETUP_ANDX *)smb_buffer; |
2905 | pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response; | 2926 | pSMBr = (SESSION_SETUP_ANDX *)smb_buffer_response; |
2906 | 2927 | ||
2907 | /* send SMBsessionSetup here */ | 2928 | /* send SMBsessionSetup here */ |
2908 | header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX, | 2929 | header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX, |
@@ -2921,7 +2942,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
2921 | smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; | 2942 | smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; |
2922 | 2943 | ||
2923 | capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS | | 2944 | capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS | |
2924 | CAP_EXTENDED_SECURITY; | 2945 | CAP_EXTENDED_SECURITY; |
2925 | if (ses->capabilities & CAP_UNICODE) { | 2946 | if (ses->capabilities & CAP_UNICODE) { |
2926 | smb_buffer->Flags2 |= SMBFLG2_UNICODE; | 2947 | smb_buffer->Flags2 |= SMBFLG2_UNICODE; |
2927 | capabilities |= CAP_UNICODE; | 2948 | capabilities |= CAP_UNICODE; |
@@ -2936,15 +2957,14 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
2936 | } | 2957 | } |
2937 | pSMB->req.Capabilities = cpu_to_le32(capabilities); | 2958 | pSMB->req.Capabilities = cpu_to_le32(capabilities); |
2938 | 2959 | ||
2939 | bcc_ptr = (char *) &pSMB->req.SecurityBlob; | 2960 | bcc_ptr = (char *)&pSMB->req.SecurityBlob; |
2940 | SecurityBlob = (PAUTHENTICATE_MESSAGE) bcc_ptr; | 2961 | SecurityBlob = (PAUTHENTICATE_MESSAGE)bcc_ptr; |
2941 | strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8); | 2962 | strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8); |
2942 | SecurityBlob->MessageType = NtLmAuthenticate; | 2963 | SecurityBlob->MessageType = NtLmAuthenticate; |
2943 | bcc_ptr += SecurityBlobLength; | 2964 | bcc_ptr += SecurityBlobLength; |
2944 | negotiate_flags = | 2965 | negotiate_flags = NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET | |
2945 | NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET | | 2966 | NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO | |
2946 | NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO | | 2967 | 0x80000000 | NTLMSSP_NEGOTIATE_128; |
2947 | 0x80000000 | NTLMSSP_NEGOTIATE_128; | ||
2948 | if (sign_CIFS_PDUs) | 2968 | if (sign_CIFS_PDUs) |
2949 | negotiate_flags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN; | 2969 | negotiate_flags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN; |
2950 | if (ntlmv2_flag) | 2970 | if (ntlmv2_flag) |
@@ -2979,36 +2999,32 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
2979 | SecurityBlob->DomainName.Length = 0; | 2999 | SecurityBlob->DomainName.Length = 0; |
2980 | SecurityBlob->DomainName.MaximumLength = 0; | 3000 | SecurityBlob->DomainName.MaximumLength = 0; |
2981 | } else { | 3001 | } else { |
2982 | __u16 len = | 3002 | __u16 ln = cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64, |
2983 | cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64, | ||
2984 | nls_codepage); | 3003 | nls_codepage); |
2985 | len *= 2; | 3004 | ln *= 2; |
2986 | SecurityBlob->DomainName.MaximumLength = | 3005 | SecurityBlob->DomainName.MaximumLength = |
2987 | cpu_to_le16(len); | 3006 | cpu_to_le16(ln); |
2988 | SecurityBlob->DomainName.Buffer = | 3007 | SecurityBlob->DomainName.Buffer = |
2989 | cpu_to_le32(SecurityBlobLength); | 3008 | cpu_to_le32(SecurityBlobLength); |
2990 | bcc_ptr += len; | 3009 | bcc_ptr += ln; |
2991 | SecurityBlobLength += len; | 3010 | SecurityBlobLength += ln; |
2992 | SecurityBlob->DomainName.Length = | 3011 | SecurityBlob->DomainName.Length = cpu_to_le16(ln); |
2993 | cpu_to_le16(len); | ||
2994 | } | 3012 | } |
2995 | if (user == NULL) { | 3013 | if (user == NULL) { |
2996 | SecurityBlob->UserName.Buffer = 0; | 3014 | SecurityBlob->UserName.Buffer = 0; |
2997 | SecurityBlob->UserName.Length = 0; | 3015 | SecurityBlob->UserName.Length = 0; |
2998 | SecurityBlob->UserName.MaximumLength = 0; | 3016 | SecurityBlob->UserName.MaximumLength = 0; |
2999 | } else { | 3017 | } else { |
3000 | __u16 len = | 3018 | __u16 ln = cifs_strtoUCS((__le16 *) bcc_ptr, user, 64, |
3001 | cifs_strtoUCS((__le16 *) bcc_ptr, user, 64, | ||
3002 | nls_codepage); | 3019 | nls_codepage); |
3003 | len *= 2; | 3020 | ln *= 2; |
3004 | SecurityBlob->UserName.MaximumLength = | 3021 | SecurityBlob->UserName.MaximumLength = |
3005 | cpu_to_le16(len); | 3022 | cpu_to_le16(ln); |
3006 | SecurityBlob->UserName.Buffer = | 3023 | SecurityBlob->UserName.Buffer = |
3007 | cpu_to_le32(SecurityBlobLength); | 3024 | cpu_to_le32(SecurityBlobLength); |
3008 | bcc_ptr += len; | 3025 | bcc_ptr += ln; |
3009 | SecurityBlobLength += len; | 3026 | SecurityBlobLength += ln; |
3010 | SecurityBlob->UserName.Length = | 3027 | SecurityBlob->UserName.Length = cpu_to_le16(ln); |
3011 | cpu_to_le16(len); | ||
3012 | } | 3028 | } |
3013 | 3029 | ||
3014 | /* SecurityBlob->WorkstationName.Length = | 3030 | /* SecurityBlob->WorkstationName.Length = |
@@ -3052,33 +3068,32 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
3052 | SecurityBlob->DomainName.Length = 0; | 3068 | SecurityBlob->DomainName.Length = 0; |
3053 | SecurityBlob->DomainName.MaximumLength = 0; | 3069 | SecurityBlob->DomainName.MaximumLength = 0; |
3054 | } else { | 3070 | } else { |
3055 | __u16 len; | 3071 | __u16 ln; |
3056 | negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED; | 3072 | negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED; |
3057 | strncpy(bcc_ptr, domain, 63); | 3073 | strncpy(bcc_ptr, domain, 63); |
3058 | len = strnlen(domain, 64); | 3074 | ln = strnlen(domain, 64); |
3059 | SecurityBlob->DomainName.MaximumLength = | 3075 | SecurityBlob->DomainName.MaximumLength = |
3060 | cpu_to_le16(len); | 3076 | cpu_to_le16(ln); |
3061 | SecurityBlob->DomainName.Buffer = | 3077 | SecurityBlob->DomainName.Buffer = |
3062 | cpu_to_le32(SecurityBlobLength); | 3078 | cpu_to_le32(SecurityBlobLength); |
3063 | bcc_ptr += len; | 3079 | bcc_ptr += ln; |
3064 | SecurityBlobLength += len; | 3080 | SecurityBlobLength += ln; |
3065 | SecurityBlob->DomainName.Length = cpu_to_le16(len); | 3081 | SecurityBlob->DomainName.Length = cpu_to_le16(ln); |
3066 | } | 3082 | } |
3067 | if (user == NULL) { | 3083 | if (user == NULL) { |
3068 | SecurityBlob->UserName.Buffer = 0; | 3084 | SecurityBlob->UserName.Buffer = 0; |
3069 | SecurityBlob->UserName.Length = 0; | 3085 | SecurityBlob->UserName.Length = 0; |
3070 | SecurityBlob->UserName.MaximumLength = 0; | 3086 | SecurityBlob->UserName.MaximumLength = 0; |
3071 | } else { | 3087 | } else { |
3072 | __u16 len; | 3088 | __u16 ln; |
3073 | strncpy(bcc_ptr, user, 63); | 3089 | strncpy(bcc_ptr, user, 63); |
3074 | len = strnlen(user, 64); | 3090 | ln = strnlen(user, 64); |
3075 | SecurityBlob->UserName.MaximumLength = | 3091 | SecurityBlob->UserName.MaximumLength = cpu_to_le16(ln); |
3076 | cpu_to_le16(len); | ||
3077 | SecurityBlob->UserName.Buffer = | 3092 | SecurityBlob->UserName.Buffer = |
3078 | cpu_to_le32(SecurityBlobLength); | 3093 | cpu_to_le32(SecurityBlobLength); |
3079 | bcc_ptr += len; | 3094 | bcc_ptr += ln; |
3080 | SecurityBlobLength += len; | 3095 | SecurityBlobLength += ln; |
3081 | SecurityBlob->UserName.Length = cpu_to_le16(len); | 3096 | SecurityBlob->UserName.Length = cpu_to_le16(ln); |
3082 | } | 3097 | } |
3083 | /* BB fill in our workstation name if known BB */ | 3098 | /* BB fill in our workstation name if known BB */ |
3084 | 3099 | ||
@@ -3098,14 +3113,13 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
3098 | pSMB->req.ByteCount = cpu_to_le16(count); | 3113 | pSMB->req.ByteCount = cpu_to_le16(count); |
3099 | 3114 | ||
3100 | rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, | 3115 | rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, |
3101 | &bytes_returned, 1); | 3116 | &bytes_returned, CIFS_LONG_OP); |
3102 | if (rc) { | 3117 | if (rc) { |
3103 | /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */ | 3118 | /* rc = map_smb_to_linux_error(smb_buffer_response) done in SendReceive now */ |
3104 | } else if ((smb_buffer_response->WordCount == 3) | 3119 | } else if ((smb_buffer_response->WordCount == 3) || |
3105 | || (smb_buffer_response->WordCount == 4)) { | 3120 | (smb_buffer_response->WordCount == 4)) { |
3106 | __u16 action = le16_to_cpu(pSMBr->resp.Action); | 3121 | __u16 action = le16_to_cpu(pSMBr->resp.Action); |
3107 | __u16 blob_len = | 3122 | __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength); |
3108 | le16_to_cpu(pSMBr->resp.SecurityBlobLength); | ||
3109 | if (action & GUEST_LOGIN) | 3123 | if (action & GUEST_LOGIN) |
3110 | cFYI(1, (" Guest login")); /* BB Should we set anything | 3124 | cFYI(1, (" Guest login")); /* BB Should we set anything |
3111 | in SesInfo struct ? */ | 3125 | in SesInfo struct ? */ |
@@ -3145,8 +3159,8 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
3145 | } else { | 3159 | } else { |
3146 | remaining_words = BCC(smb_buffer_response) / 2; | 3160 | remaining_words = BCC(smb_buffer_response) / 2; |
3147 | } | 3161 | } |
3148 | len = | 3162 | len = UniStrnlen((wchar_t *) bcc_ptr, |
3149 | UniStrnlen((wchar_t *) bcc_ptr,remaining_words - 1); | 3163 | remaining_words - 1); |
3150 | /* We look for obvious messed up bcc or strings in response so we do not go off | 3164 | /* We look for obvious messed up bcc or strings in response so we do not go off |
3151 | the end since (at least) WIN2K and Windows XP have a major bug in not null | 3165 | the end since (at least) WIN2K and Windows XP have a major bug in not null |
3152 | terminating last Unicode string in response */ | 3166 | terminating last Unicode string in response */ |
@@ -3230,7 +3244,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
3230 | <= BCC(smb_buffer_response)) { | 3244 | <= BCC(smb_buffer_response)) { |
3231 | if (ses->serverOS) | 3245 | if (ses->serverOS) |
3232 | kfree(ses->serverOS); | 3246 | kfree(ses->serverOS); |
3233 | ses->serverOS = kzalloc(len + 1,GFP_KERNEL); | 3247 | ses->serverOS = kzalloc(len + 1, GFP_KERNEL); |
3234 | strncpy(ses->serverOS,bcc_ptr, len); | 3248 | strncpy(ses->serverOS,bcc_ptr, len); |
3235 | 3249 | ||
3236 | bcc_ptr += len; | 3250 | bcc_ptr += len; |
@@ -3259,28 +3273,24 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
3259 | bcc_ptr[0] = 0; | 3273 | bcc_ptr[0] = 0; |
3260 | bcc_ptr++; | 3274 | bcc_ptr++; |
3261 | } else | 3275 | } else |
3262 | cFYI(1, | 3276 | cFYI(1, ("field of length %d " |
3263 | ("field of length %d " | ||
3264 | "extends beyond end of smb ", | 3277 | "extends beyond end of smb ", |
3265 | len)); | 3278 | len)); |
3266 | } | 3279 | } |
3267 | } else { | 3280 | } else { |
3268 | cERROR(1, | 3281 | cERROR(1, ("Security Blob extends beyond end " |
3269 | (" Security Blob extends beyond end " | ||
3270 | "of SMB")); | 3282 | "of SMB")); |
3271 | } | 3283 | } |
3272 | } else { | 3284 | } else { |
3273 | cERROR(1, ("No session structure passed in.")); | 3285 | cERROR(1, ("No session structure passed in.")); |
3274 | } | 3286 | } |
3275 | } else { | 3287 | } else { |
3276 | cERROR(1, | 3288 | cERROR(1, ("Invalid Word count %d: ", |
3277 | (" Invalid Word count %d: ", | ||
3278 | smb_buffer_response->WordCount)); | 3289 | smb_buffer_response->WordCount)); |
3279 | rc = -EIO; | 3290 | rc = -EIO; |
3280 | } | 3291 | } |
3281 | 3292 | ||
3282 | if (smb_buffer) | 3293 | cifs_buf_release(smb_buffer); |
3283 | cifs_buf_release(smb_buffer); | ||
3284 | 3294 | ||
3285 | return rc; | 3295 | return rc; |
3286 | } | 3296 | } |
@@ -3379,7 +3389,8 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, | |||
3379 | pSMB->hdr.smb_buf_length += count; | 3389 | pSMB->hdr.smb_buf_length += count; |
3380 | pSMB->ByteCount = cpu_to_le16(count); | 3390 | pSMB->ByteCount = cpu_to_le16(count); |
3381 | 3391 | ||
3382 | rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length, 0); | 3392 | rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length, |
3393 | CIFS_STD_OP); | ||
3383 | 3394 | ||
3384 | /* if (rc) rc = map_smb_to_linux_error(smb_buffer_response); */ | 3395 | /* if (rc) rc = map_smb_to_linux_error(smb_buffer_response); */ |
3385 | /* above now done in SendReceive */ | 3396 | /* above now done in SendReceive */ |
@@ -3389,6 +3400,18 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, | |||
3389 | bcc_ptr = pByteArea(smb_buffer_response); | 3400 | bcc_ptr = pByteArea(smb_buffer_response); |
3390 | length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2); | 3401 | length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2); |
3391 | /* skip service field (NB: this field is always ASCII) */ | 3402 | /* skip service field (NB: this field is always ASCII) */ |
3403 | if (length == 3) { | ||
3404 | if ((bcc_ptr[0] == 'I') && (bcc_ptr[1] == 'P') && | ||
3405 | (bcc_ptr[2] == 'C')) { | ||
3406 | cFYI(1, ("IPC connection")); | ||
3407 | tcon->ipc = 1; | ||
3408 | } | ||
3409 | } else if (length == 2) { | ||
3410 | if ((bcc_ptr[0] == 'A') && (bcc_ptr[1] == ':')) { | ||
3411 | /* the most common case */ | ||
3412 | cFYI(1, ("disk share connection")); | ||
3413 | } | ||
3414 | } | ||
3392 | bcc_ptr += length + 1; | 3415 | bcc_ptr += length + 1; |
3393 | strncpy(tcon->treeName, tree, MAX_TREE_SIZE); | 3416 | strncpy(tcon->treeName, tree, MAX_TREE_SIZE); |
3394 | if (smb_buffer->Flags2 & SMBFLG2_UNICODE) { | 3417 | if (smb_buffer->Flags2 & SMBFLG2_UNICODE) { |
@@ -3399,9 +3422,11 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, | |||
3399 | kfree(tcon->nativeFileSystem); | 3422 | kfree(tcon->nativeFileSystem); |
3400 | tcon->nativeFileSystem = | 3423 | tcon->nativeFileSystem = |
3401 | kzalloc(length + 2, GFP_KERNEL); | 3424 | kzalloc(length + 2, GFP_KERNEL); |
3402 | cifs_strfromUCS_le(tcon->nativeFileSystem, | 3425 | if (tcon->nativeFileSystem) |
3403 | (__le16 *) bcc_ptr, | 3426 | cifs_strfromUCS_le( |
3404 | length, nls_codepage); | 3427 | tcon->nativeFileSystem, |
3428 | (__le16 *) bcc_ptr, | ||
3429 | length, nls_codepage); | ||
3405 | bcc_ptr += 2 * length; | 3430 | bcc_ptr += 2 * length; |
3406 | bcc_ptr[0] = 0; /* null terminate the string */ | 3431 | bcc_ptr[0] = 0; /* null terminate the string */ |
3407 | bcc_ptr[1] = 0; | 3432 | bcc_ptr[1] = 0; |
@@ -3416,8 +3441,9 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, | |||
3416 | kfree(tcon->nativeFileSystem); | 3441 | kfree(tcon->nativeFileSystem); |
3417 | tcon->nativeFileSystem = | 3442 | tcon->nativeFileSystem = |
3418 | kzalloc(length + 1, GFP_KERNEL); | 3443 | kzalloc(length + 1, GFP_KERNEL); |
3419 | strncpy(tcon->nativeFileSystem, bcc_ptr, | 3444 | if (tcon->nativeFileSystem) |
3420 | length); | 3445 | strncpy(tcon->nativeFileSystem, bcc_ptr, |
3446 | length); | ||
3421 | } | 3447 | } |
3422 | /* else do not bother copying these information fields*/ | 3448 | /* else do not bother copying these information fields*/ |
3423 | } | 3449 | } |
@@ -3433,8 +3459,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, | |||
3433 | ses->ipc_tid = smb_buffer_response->Tid; | 3459 | ses->ipc_tid = smb_buffer_response->Tid; |
3434 | } | 3460 | } |
3435 | 3461 | ||
3436 | if (smb_buffer) | 3462 | cifs_buf_release(smb_buffer); |
3437 | cifs_buf_release(smb_buffer); | ||
3438 | return rc; | 3463 | return rc; |
3439 | } | 3464 | } |
3440 | 3465 | ||
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index 4830acc86d74..37dc97af1487 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * vfs operations that deal with dentries | 4 | * vfs operations that deal with dentries |
5 | * | 5 | * |
6 | * Copyright (C) International Business Machines Corp., 2002,2005 | 6 | * Copyright (C) International Business Machines Corp., 2002,2007 |
7 | * Author(s): Steve French (sfrench@us.ibm.com) | 7 | * Author(s): Steve French (sfrench@us.ibm.com) |
8 | * | 8 | * |
9 | * This library is free software; you can redistribute it and/or modify | 9 | * This library is free software; you can redistribute it and/or modify |
@@ -269,7 +269,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, | |||
269 | CIFSSMBClose(xid, pTcon, fileHandle); | 269 | CIFSSMBClose(xid, pTcon, fileHandle); |
270 | } else if (newinode) { | 270 | } else if (newinode) { |
271 | pCifsFile = | 271 | pCifsFile = |
272 | kzalloc(sizeof (struct cifsFileInfo), GFP_KERNEL); | 272 | kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL); |
273 | 273 | ||
274 | if (pCifsFile == NULL) | 274 | if (pCifsFile == NULL) |
275 | goto cifs_create_out; | 275 | goto cifs_create_out; |
@@ -397,7 +397,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, | |||
397 | /* BB Do not bother to decode buf since no | 397 | /* BB Do not bother to decode buf since no |
398 | local inode yet to put timestamps in, | 398 | local inode yet to put timestamps in, |
399 | but we can reuse it safely */ | 399 | but we can reuse it safely */ |
400 | int bytes_written; | 400 | unsigned int bytes_written; |
401 | struct win_dev *pdev; | 401 | struct win_dev *pdev; |
402 | pdev = (struct win_dev *)buf; | 402 | pdev = (struct win_dev *)buf; |
403 | if (S_ISCHR(mode)) { | 403 | if (S_ISCHR(mode)) { |
@@ -450,8 +450,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, | |||
450 | 450 | ||
451 | xid = GetXid(); | 451 | xid = GetXid(); |
452 | 452 | ||
453 | cFYI(1, | 453 | cFYI(1, (" parent inode = 0x%p name is: %s and dentry = 0x%p", |
454 | (" parent inode = 0x%p name is: %s and dentry = 0x%p", | ||
455 | parent_dir_inode, direntry->d_name.name, direntry)); | 454 | parent_dir_inode, direntry->d_name.name, direntry)); |
456 | 455 | ||
457 | /* check whether path exists */ | 456 | /* check whether path exists */ |
@@ -594,7 +593,7 @@ static int cifs_ci_compare(struct dentry *dentry, struct qstr *a, | |||
594 | * case take precedence. If a is not a negative dentry, this | 593 | * case take precedence. If a is not a negative dentry, this |
595 | * should have no side effects | 594 | * should have no side effects |
596 | */ | 595 | */ |
597 | memcpy((unsigned char *)a->name, b->name, a->len); | 596 | memcpy(a->name, b->name, a->len); |
598 | return 0; | 597 | return 0; |
599 | } | 598 | } |
600 | return 1; | 599 | return 1; |
diff --git a/fs/cifs/export.c b/fs/cifs/export.c index 893fd0aebff8..75949d6a5f1b 100644 --- a/fs/cifs/export.c +++ b/fs/cifs/export.c | |||
@@ -43,6 +43,7 @@ | |||
43 | #include <linux/exportfs.h> | 43 | #include <linux/exportfs.h> |
44 | #include "cifsglob.h" | 44 | #include "cifsglob.h" |
45 | #include "cifs_debug.h" | 45 | #include "cifs_debug.h" |
46 | #include "cifsfs.h" | ||
46 | 47 | ||
47 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 48 | #ifdef CONFIG_CIFS_EXPERIMENTAL |
48 | static struct dentry *cifs_get_parent(struct dentry *dentry) | 49 | static struct dentry *cifs_get_parent(struct dentry *dentry) |
@@ -52,7 +53,7 @@ static struct dentry *cifs_get_parent(struct dentry *dentry) | |||
52 | return ERR_PTR(-EACCES); | 53 | return ERR_PTR(-EACCES); |
53 | } | 54 | } |
54 | 55 | ||
55 | struct export_operations cifs_export_ops = { | 56 | const struct export_operations cifs_export_ops = { |
56 | .get_parent = cifs_get_parent, | 57 | .get_parent = cifs_get_parent, |
57 | /* Following five export operations are unneeded so far and can default: | 58 | /* Following five export operations are unneeded so far and can default: |
58 | .get_dentry = | 59 | .get_dentry = |
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 894b1f7b299d..dd26e2759b17 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
@@ -130,7 +130,9 @@ static inline int cifs_open_inode_helper(struct inode *inode, struct file *file, | |||
130 | if (file->f_path.dentry->d_inode->i_mapping) { | 130 | if (file->f_path.dentry->d_inode->i_mapping) { |
131 | /* BB no need to lock inode until after invalidate | 131 | /* BB no need to lock inode until after invalidate |
132 | since namei code should already have it locked? */ | 132 | since namei code should already have it locked? */ |
133 | filemap_write_and_wait(file->f_path.dentry->d_inode->i_mapping); | 133 | rc = filemap_write_and_wait(file->f_path.dentry->d_inode->i_mapping); |
134 | if (rc != 0) | ||
135 | CIFS_I(file->f_path.dentry->d_inode)->write_behind_rc = rc; | ||
134 | } | 136 | } |
135 | cFYI(1, ("invalidating remote inode since open detected it " | 137 | cFYI(1, ("invalidating remote inode since open detected it " |
136 | "changed")); | 138 | "changed")); |
@@ -425,7 +427,9 @@ reopen_error_exit: | |||
425 | pCifsInode = CIFS_I(inode); | 427 | pCifsInode = CIFS_I(inode); |
426 | if (pCifsInode) { | 428 | if (pCifsInode) { |
427 | if (can_flush) { | 429 | if (can_flush) { |
428 | filemap_write_and_wait(inode->i_mapping); | 430 | rc = filemap_write_and_wait(inode->i_mapping); |
431 | if (rc != 0) | ||
432 | CIFS_I(inode)->write_behind_rc = rc; | ||
429 | /* temporarily disable caching while we | 433 | /* temporarily disable caching while we |
430 | go to server to get inode info */ | 434 | go to server to get inode info */ |
431 | pCifsInode->clientCanCacheAll = FALSE; | 435 | pCifsInode->clientCanCacheAll = FALSE; |
@@ -467,7 +471,7 @@ reopen_error_exit: | |||
467 | int cifs_close(struct inode *inode, struct file *file) | 471 | int cifs_close(struct inode *inode, struct file *file) |
468 | { | 472 | { |
469 | int rc = 0; | 473 | int rc = 0; |
470 | int xid; | 474 | int xid, timeout; |
471 | struct cifs_sb_info *cifs_sb; | 475 | struct cifs_sb_info *cifs_sb; |
472 | struct cifsTconInfo *pTcon; | 476 | struct cifsTconInfo *pTcon; |
473 | struct cifsFileInfo *pSMBFile = | 477 | struct cifsFileInfo *pSMBFile = |
@@ -485,9 +489,9 @@ int cifs_close(struct inode *inode, struct file *file) | |||
485 | /* no sense reconnecting to close a file that is | 489 | /* no sense reconnecting to close a file that is |
486 | already closed */ | 490 | already closed */ |
487 | if (pTcon->tidStatus != CifsNeedReconnect) { | 491 | if (pTcon->tidStatus != CifsNeedReconnect) { |
488 | int timeout = 2; | 492 | timeout = 2; |
489 | while ((atomic_read(&pSMBFile->wrtPending) != 0) | 493 | while ((atomic_read(&pSMBFile->wrtPending) != 0) |
490 | && (timeout < 1000) ) { | 494 | && (timeout <= 2048)) { |
491 | /* Give write a better chance to get to | 495 | /* Give write a better chance to get to |
492 | server ahead of the close. We do not | 496 | server ahead of the close. We do not |
493 | want to add a wait_q here as it would | 497 | want to add a wait_q here as it would |
@@ -522,12 +526,30 @@ int cifs_close(struct inode *inode, struct file *file) | |||
522 | list_del(&pSMBFile->flist); | 526 | list_del(&pSMBFile->flist); |
523 | list_del(&pSMBFile->tlist); | 527 | list_del(&pSMBFile->tlist); |
524 | write_unlock(&GlobalSMBSeslock); | 528 | write_unlock(&GlobalSMBSeslock); |
529 | timeout = 10; | ||
530 | /* We waited above to give the SMBWrite a chance to issue | ||
531 | on the wire (so we do not get SMBWrite returning EBADF | ||
532 | if writepages is racing with close. Note that writepages | ||
533 | does not specify a file handle, so it is possible for a file | ||
534 | to be opened twice, and the application close the "wrong" | ||
535 | file handle - in these cases we delay long enough to allow | ||
536 | the SMBWrite to get on the wire before the SMB Close. | ||
537 | We allow total wait here over 45 seconds, more than | ||
538 | oplock break time, and more than enough to allow any write | ||
539 | to complete on the server, or to time out on the client */ | ||
540 | while ((atomic_read(&pSMBFile->wrtPending) != 0) | ||
541 | && (timeout <= 50000)) { | ||
542 | cERROR(1, ("writes pending, delay free of handle")); | ||
543 | msleep(timeout); | ||
544 | timeout *= 8; | ||
545 | } | ||
525 | kfree(pSMBFile->search_resume_name); | 546 | kfree(pSMBFile->search_resume_name); |
526 | kfree(file->private_data); | 547 | kfree(file->private_data); |
527 | file->private_data = NULL; | 548 | file->private_data = NULL; |
528 | } else | 549 | } else |
529 | rc = -EBADF; | 550 | rc = -EBADF; |
530 | 551 | ||
552 | read_lock(&GlobalSMBSeslock); | ||
531 | if (list_empty(&(CIFS_I(inode)->openFileList))) { | 553 | if (list_empty(&(CIFS_I(inode)->openFileList))) { |
532 | cFYI(1, ("closing last open instance for inode %p", inode)); | 554 | cFYI(1, ("closing last open instance for inode %p", inode)); |
533 | /* if the file is not open we do not know if we can cache info | 555 | /* if the file is not open we do not know if we can cache info |
@@ -535,6 +557,7 @@ int cifs_close(struct inode *inode, struct file *file) | |||
535 | CIFS_I(inode)->clientCanCacheRead = FALSE; | 557 | CIFS_I(inode)->clientCanCacheRead = FALSE; |
536 | CIFS_I(inode)->clientCanCacheAll = FALSE; | 558 | CIFS_I(inode)->clientCanCacheAll = FALSE; |
537 | } | 559 | } |
560 | read_unlock(&GlobalSMBSeslock); | ||
538 | if ((rc == 0) && CIFS_I(inode)->write_behind_rc) | 561 | if ((rc == 0) && CIFS_I(inode)->write_behind_rc) |
539 | rc = CIFS_I(inode)->write_behind_rc; | 562 | rc = CIFS_I(inode)->write_behind_rc; |
540 | FreeXid(xid); | 563 | FreeXid(xid); |
@@ -767,7 +790,8 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) | |||
767 | mutex_lock(&fid->lock_mutex); | 790 | mutex_lock(&fid->lock_mutex); |
768 | list_for_each_entry_safe(li, tmp, &fid->llist, llist) { | 791 | list_for_each_entry_safe(li, tmp, &fid->llist, llist) { |
769 | if (pfLock->fl_start <= li->offset && | 792 | if (pfLock->fl_start <= li->offset && |
770 | length >= li->length) { | 793 | (pfLock->fl_start + length) >= |
794 | (li->offset + li->length)) { | ||
771 | stored_rc = CIFSSMBLock(xid, pTcon, | 795 | stored_rc = CIFSSMBLock(xid, pTcon, |
772 | netfid, | 796 | netfid, |
773 | li->length, li->offset, | 797 | li->length, li->offset, |
@@ -815,9 +839,9 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data, | |||
815 | xid = GetXid(); | 839 | xid = GetXid(); |
816 | 840 | ||
817 | if (*poffset > file->f_path.dentry->d_inode->i_size) | 841 | if (*poffset > file->f_path.dentry->d_inode->i_size) |
818 | long_op = 2; /* writes past end of file can take a long time */ | 842 | long_op = CIFS_VLONG_OP; /* writes past EOF take long time */ |
819 | else | 843 | else |
820 | long_op = 1; | 844 | long_op = CIFS_LONG_OP; |
821 | 845 | ||
822 | for (total_written = 0; write_size > total_written; | 846 | for (total_written = 0; write_size > total_written; |
823 | total_written += bytes_written) { | 847 | total_written += bytes_written) { |
@@ -864,7 +888,7 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data, | |||
864 | } | 888 | } |
865 | } else | 889 | } else |
866 | *poffset += bytes_written; | 890 | *poffset += bytes_written; |
867 | long_op = FALSE; /* subsequent writes fast - | 891 | long_op = CIFS_STD_OP; /* subsequent writes fast - |
868 | 15 seconds is plenty */ | 892 | 15 seconds is plenty */ |
869 | } | 893 | } |
870 | 894 | ||
@@ -914,9 +938,9 @@ static ssize_t cifs_write(struct file *file, const char *write_data, | |||
914 | xid = GetXid(); | 938 | xid = GetXid(); |
915 | 939 | ||
916 | if (*poffset > file->f_path.dentry->d_inode->i_size) | 940 | if (*poffset > file->f_path.dentry->d_inode->i_size) |
917 | long_op = 2; /* writes past end of file can take a long time */ | 941 | long_op = CIFS_VLONG_OP; /* writes past EOF can be slow */ |
918 | else | 942 | else |
919 | long_op = 1; | 943 | long_op = CIFS_LONG_OP; |
920 | 944 | ||
921 | for (total_written = 0; write_size > total_written; | 945 | for (total_written = 0; write_size > total_written; |
922 | total_written += bytes_written) { | 946 | total_written += bytes_written) { |
@@ -982,7 +1006,7 @@ static ssize_t cifs_write(struct file *file, const char *write_data, | |||
982 | } | 1006 | } |
983 | } else | 1007 | } else |
984 | *poffset += bytes_written; | 1008 | *poffset += bytes_written; |
985 | long_op = FALSE; /* subsequent writes fast - | 1009 | long_op = CIFS_STD_OP; /* subsequent writes fast - |
986 | 15 seconds is plenty */ | 1010 | 15 seconds is plenty */ |
987 | } | 1011 | } |
988 | 1012 | ||
@@ -1006,6 +1030,37 @@ static ssize_t cifs_write(struct file *file, const char *write_data, | |||
1006 | return total_written; | 1030 | return total_written; |
1007 | } | 1031 | } |
1008 | 1032 | ||
1033 | #ifdef CONFIG_CIFS_EXPERIMENTAL | ||
1034 | struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode) | ||
1035 | { | ||
1036 | struct cifsFileInfo *open_file = NULL; | ||
1037 | |||
1038 | read_lock(&GlobalSMBSeslock); | ||
1039 | /* we could simply get the first_list_entry since write-only entries | ||
1040 | are always at the end of the list but since the first entry might | ||
1041 | have a close pending, we go through the whole list */ | ||
1042 | list_for_each_entry(open_file, &cifs_inode->openFileList, flist) { | ||
1043 | if (open_file->closePend) | ||
1044 | continue; | ||
1045 | if (open_file->pfile && ((open_file->pfile->f_flags & O_RDWR) || | ||
1046 | (open_file->pfile->f_flags & O_RDONLY))) { | ||
1047 | if (!open_file->invalidHandle) { | ||
1048 | /* found a good file */ | ||
1049 | /* lock it so it will not be closed on us */ | ||
1050 | atomic_inc(&open_file->wrtPending); | ||
1051 | read_unlock(&GlobalSMBSeslock); | ||
1052 | return open_file; | ||
1053 | } /* else might as well continue, and look for | ||
1054 | another, or simply have the caller reopen it | ||
1055 | again rather than trying to fix this handle */ | ||
1056 | } else /* write only file */ | ||
1057 | break; /* write only files are last so must be done */ | ||
1058 | } | ||
1059 | read_unlock(&GlobalSMBSeslock); | ||
1060 | return NULL; | ||
1061 | } | ||
1062 | #endif | ||
1063 | |||
1009 | struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode) | 1064 | struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode) |
1010 | { | 1065 | { |
1011 | struct cifsFileInfo *open_file; | 1066 | struct cifsFileInfo *open_file; |
@@ -1022,6 +1077,7 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode) | |||
1022 | } | 1077 | } |
1023 | 1078 | ||
1024 | read_lock(&GlobalSMBSeslock); | 1079 | read_lock(&GlobalSMBSeslock); |
1080 | refind_writable: | ||
1025 | list_for_each_entry(open_file, &cifs_inode->openFileList, flist) { | 1081 | list_for_each_entry(open_file, &cifs_inode->openFileList, flist) { |
1026 | if (open_file->closePend) | 1082 | if (open_file->closePend) |
1027 | continue; | 1083 | continue; |
@@ -1029,24 +1085,49 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode) | |||
1029 | ((open_file->pfile->f_flags & O_RDWR) || | 1085 | ((open_file->pfile->f_flags & O_RDWR) || |
1030 | (open_file->pfile->f_flags & O_WRONLY))) { | 1086 | (open_file->pfile->f_flags & O_WRONLY))) { |
1031 | atomic_inc(&open_file->wrtPending); | 1087 | atomic_inc(&open_file->wrtPending); |
1088 | |||
1089 | if (!open_file->invalidHandle) { | ||
1090 | /* found a good writable file */ | ||
1091 | read_unlock(&GlobalSMBSeslock); | ||
1092 | return open_file; | ||
1093 | } | ||
1094 | |||
1032 | read_unlock(&GlobalSMBSeslock); | 1095 | read_unlock(&GlobalSMBSeslock); |
1033 | if ((open_file->invalidHandle) && | 1096 | /* Had to unlock since following call can block */ |
1034 | (!open_file->closePend) /* BB fixme -since the second clause can not be true remove it BB */) { | 1097 | rc = cifs_reopen_file(open_file->pfile, FALSE); |
1035 | rc = cifs_reopen_file(open_file->pfile, FALSE); | 1098 | if (!rc) { |
1036 | /* if it fails, try another handle - might be */ | 1099 | if (!open_file->closePend) |
1037 | /* dangerous to hold up writepages with retry */ | 1100 | return open_file; |
1038 | if (rc) { | 1101 | else { /* start over in case this was deleted */ |
1039 | cFYI(1, | 1102 | /* since the list could be modified */ |
1040 | ("failed on reopen file in wp")); | ||
1041 | read_lock(&GlobalSMBSeslock); | 1103 | read_lock(&GlobalSMBSeslock); |
1042 | /* can not use this handle, no write | 1104 | atomic_dec(&open_file->wrtPending); |
1043 | pending on this one after all */ | 1105 | goto refind_writable; |
1044 | atomic_dec | ||
1045 | (&open_file->wrtPending); | ||
1046 | continue; | ||
1047 | } | 1106 | } |
1048 | } | 1107 | } |
1049 | return open_file; | 1108 | |
1109 | /* if it fails, try another handle if possible - | ||
1110 | (we can not do this if closePending since | ||
1111 | loop could be modified - in which case we | ||
1112 | have to start at the beginning of the list | ||
1113 | again. Note that it would be bad | ||
1114 | to hold up writepages here (rather than | ||
1115 | in caller) with continuous retries */ | ||
1116 | cFYI(1, ("wp failed on reopen file")); | ||
1117 | read_lock(&GlobalSMBSeslock); | ||
1118 | /* can not use this handle, no write | ||
1119 | pending on this one after all */ | ||
1120 | atomic_dec(&open_file->wrtPending); | ||
1121 | |||
1122 | if (open_file->closePend) /* list could have changed */ | ||
1123 | goto refind_writable; | ||
1124 | /* else we simply continue to the next entry. Thus | ||
1125 | we do not loop on reopen errors. If we | ||
1126 | can not reopen the file, for example if we | ||
1127 | reconnected to a server with another client | ||
1128 | racing to delete or lock the file we would not | ||
1129 | make progress if we restarted before the beginning | ||
1130 | of the loop here. */ | ||
1050 | } | 1131 | } |
1051 | } | 1132 | } |
1052 | read_unlock(&GlobalSMBSeslock); | 1133 | read_unlock(&GlobalSMBSeslock); |
@@ -1283,14 +1364,17 @@ retry: | |||
1283 | open_file->netfid, | 1364 | open_file->netfid, |
1284 | bytes_to_write, offset, | 1365 | bytes_to_write, offset, |
1285 | &bytes_written, iov, n_iov, | 1366 | &bytes_written, iov, n_iov, |
1286 | 1); | 1367 | CIFS_LONG_OP); |
1287 | atomic_dec(&open_file->wrtPending); | 1368 | atomic_dec(&open_file->wrtPending); |
1288 | if (rc || bytes_written < bytes_to_write) { | 1369 | if (rc || bytes_written < bytes_to_write) { |
1289 | cERROR(1, ("Write2 ret %d, wrote %d", | 1370 | cERROR(1, ("Write2 ret %d, wrote %d", |
1290 | rc, bytes_written)); | 1371 | rc, bytes_written)); |
1291 | /* BB what if continued retry is | 1372 | /* BB what if continued retry is |
1292 | requested via mount flags? */ | 1373 | requested via mount flags? */ |
1293 | set_bit(AS_EIO, &mapping->flags); | 1374 | if (rc == -ENOSPC) |
1375 | set_bit(AS_ENOSPC, &mapping->flags); | ||
1376 | else | ||
1377 | set_bit(AS_EIO, &mapping->flags); | ||
1294 | } else { | 1378 | } else { |
1295 | cifs_stats_bytes_written(cifs_sb->tcon, | 1379 | cifs_stats_bytes_written(cifs_sb->tcon, |
1296 | bytes_written); | 1380 | bytes_written); |
@@ -1422,9 +1506,11 @@ int cifs_fsync(struct file *file, struct dentry *dentry, int datasync) | |||
1422 | cFYI(1, ("Sync file - name: %s datasync: 0x%x", | 1506 | cFYI(1, ("Sync file - name: %s datasync: 0x%x", |
1423 | dentry->d_name.name, datasync)); | 1507 | dentry->d_name.name, datasync)); |
1424 | 1508 | ||
1425 | rc = filemap_fdatawrite(inode->i_mapping); | 1509 | rc = filemap_write_and_wait(inode->i_mapping); |
1426 | if (rc == 0) | 1510 | if (rc == 0) { |
1511 | rc = CIFS_I(inode)->write_behind_rc; | ||
1427 | CIFS_I(inode)->write_behind_rc = 0; | 1512 | CIFS_I(inode)->write_behind_rc = 0; |
1513 | } | ||
1428 | FreeXid(xid); | 1514 | FreeXid(xid); |
1429 | return rc; | 1515 | return rc; |
1430 | } | 1516 | } |
@@ -1476,8 +1562,11 @@ int cifs_flush(struct file *file, fl_owner_t id) | |||
1476 | filemapfdatawrite appears easier for the time being */ | 1562 | filemapfdatawrite appears easier for the time being */ |
1477 | 1563 | ||
1478 | rc = filemap_fdatawrite(inode->i_mapping); | 1564 | rc = filemap_fdatawrite(inode->i_mapping); |
1479 | if (!rc) /* reset wb rc if we were able to write out dirty pages */ | 1565 | /* reset wb rc if we were able to write out dirty pages */ |
1566 | if (!rc) { | ||
1567 | rc = CIFS_I(inode)->write_behind_rc; | ||
1480 | CIFS_I(inode)->write_behind_rc = 0; | 1568 | CIFS_I(inode)->write_behind_rc = 0; |
1569 | } | ||
1481 | 1570 | ||
1482 | cFYI(1, ("Flush inode %p file %p rc %d", inode, file, rc)); | 1571 | cFYI(1, ("Flush inode %p file %p rc %d", inode, file, rc)); |
1483 | 1572 | ||
@@ -1709,7 +1798,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, | |||
1709 | struct page *page; | 1798 | struct page *page; |
1710 | struct cifs_sb_info *cifs_sb; | 1799 | struct cifs_sb_info *cifs_sb; |
1711 | struct cifsTconInfo *pTcon; | 1800 | struct cifsTconInfo *pTcon; |
1712 | int bytes_read = 0; | 1801 | unsigned int bytes_read = 0; |
1713 | unsigned int read_size, i; | 1802 | unsigned int read_size, i; |
1714 | char *smb_read_data = NULL; | 1803 | char *smb_read_data = NULL; |
1715 | struct smb_com_read_rsp *pSMBr; | 1804 | struct smb_com_read_rsp *pSMBr; |
@@ -1803,7 +1892,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, | |||
1803 | 1892 | ||
1804 | i += bytes_read >> PAGE_CACHE_SHIFT; | 1893 | i += bytes_read >> PAGE_CACHE_SHIFT; |
1805 | cifs_stats_bytes_read(pTcon, bytes_read); | 1894 | cifs_stats_bytes_read(pTcon, bytes_read); |
1806 | if ((int)(bytes_read & PAGE_CACHE_MASK) != bytes_read) { | 1895 | if ((bytes_read & PAGE_CACHE_MASK) != bytes_read) { |
1807 | i++; /* account for partial page */ | 1896 | i++; /* account for partial page */ |
1808 | 1897 | ||
1809 | /* server copy of file can have smaller size | 1898 | /* server copy of file can have smaller size |
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 279f3c5e0ce3..e915eb1d2e66 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -115,7 +115,7 @@ int cifs_get_inode_info_unix(struct inode **pinode, | |||
115 | inode->i_mode = le64_to_cpu(findData.Permissions); | 115 | inode->i_mode = le64_to_cpu(findData.Permissions); |
116 | /* since we set the inode type below we need to mask off | 116 | /* since we set the inode type below we need to mask off |
117 | to avoid strange results if bits set above */ | 117 | to avoid strange results if bits set above */ |
118 | inode->i_mode &= ~S_IFMT; | 118 | inode->i_mode &= ~S_IFMT; |
119 | if (type == UNIX_FILE) { | 119 | if (type == UNIX_FILE) { |
120 | inode->i_mode |= S_IFREG; | 120 | inode->i_mode |= S_IFREG; |
121 | } else if (type == UNIX_SYMLINK) { | 121 | } else if (type == UNIX_SYMLINK) { |
@@ -289,7 +289,7 @@ static int decode_sfu_inode(struct inode *inode, __u64 size, | |||
289 | 289 | ||
290 | #define SFBITS_MASK (S_ISVTX | S_ISGID | S_ISUID) /* SETFILEBITS valid bits */ | 290 | #define SFBITS_MASK (S_ISVTX | S_ISGID | S_ISUID) /* SETFILEBITS valid bits */ |
291 | 291 | ||
292 | static int get_sfu_uid_mode(struct inode *inode, | 292 | static int get_sfu_mode(struct inode *inode, |
293 | const unsigned char *path, | 293 | const unsigned char *path, |
294 | struct cifs_sb_info *cifs_sb, int xid) | 294 | struct cifs_sb_info *cifs_sb, int xid) |
295 | { | 295 | { |
@@ -527,11 +527,16 @@ int cifs_get_inode_info(struct inode **pinode, | |||
527 | 527 | ||
528 | /* BB fill in uid and gid here? with help from winbind? | 528 | /* BB fill in uid and gid here? with help from winbind? |
529 | or retrieve from NTFS stream extended attribute */ | 529 | or retrieve from NTFS stream extended attribute */ |
530 | #ifdef CONFIG_CIFS_EXPERIMENTAL | ||
531 | /* fill in 0777 bits from ACL */ | ||
532 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { | ||
533 | cFYI(1, ("Getting mode bits from ACL")); | ||
534 | acl_to_uid_mode(inode, search_path); | ||
535 | } | ||
536 | #endif | ||
530 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { | 537 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { |
531 | /* fill in uid, gid, mode from server ACL */ | 538 | /* fill in remaining high mode bits e.g. SUID, VTX */ |
532 | /* BB FIXME this should also take into account the | 539 | get_sfu_mode(inode, search_path, cifs_sb, xid); |
533 | * default uid specified on mount if present */ | ||
534 | get_sfu_uid_mode(inode, search_path, cifs_sb, xid); | ||
535 | } else if (atomic_read(&cifsInfo->inUse) == 0) { | 540 | } else if (atomic_read(&cifsInfo->inUse) == 0) { |
536 | inode->i_uid = cifs_sb->mnt_uid; | 541 | inode->i_uid = cifs_sb->mnt_uid; |
537 | inode->i_gid = cifs_sb->mnt_gid; | 542 | inode->i_gid = cifs_sb->mnt_gid; |
@@ -575,19 +580,33 @@ int cifs_get_inode_info(struct inode **pinode, | |||
575 | return rc; | 580 | return rc; |
576 | } | 581 | } |
577 | 582 | ||
583 | static const struct inode_operations cifs_ipc_inode_ops = { | ||
584 | .lookup = cifs_lookup, | ||
585 | }; | ||
586 | |||
578 | /* gets root inode */ | 587 | /* gets root inode */ |
579 | void cifs_read_inode(struct inode *inode) | 588 | void cifs_read_inode(struct inode *inode) |
580 | { | 589 | { |
581 | int xid; | 590 | int xid, rc; |
582 | struct cifs_sb_info *cifs_sb; | 591 | struct cifs_sb_info *cifs_sb; |
583 | 592 | ||
584 | cifs_sb = CIFS_SB(inode->i_sb); | 593 | cifs_sb = CIFS_SB(inode->i_sb); |
585 | xid = GetXid(); | 594 | xid = GetXid(); |
586 | 595 | ||
587 | if (cifs_sb->tcon->unix_ext) | 596 | if (cifs_sb->tcon->unix_ext) |
588 | cifs_get_inode_info_unix(&inode, "", inode->i_sb, xid); | 597 | rc = cifs_get_inode_info_unix(&inode, "", inode->i_sb, xid); |
589 | else | 598 | else |
590 | cifs_get_inode_info(&inode, "", NULL, inode->i_sb, xid); | 599 | rc = cifs_get_inode_info(&inode, "", NULL, inode->i_sb, xid); |
600 | if (rc && cifs_sb->tcon->ipc) { | ||
601 | cFYI(1, ("ipc connection - fake read inode")); | ||
602 | inode->i_mode |= S_IFDIR; | ||
603 | inode->i_nlink = 2; | ||
604 | inode->i_op = &cifs_ipc_inode_ops; | ||
605 | inode->i_fop = &simple_dir_operations; | ||
606 | inode->i_uid = cifs_sb->mnt_uid; | ||
607 | inode->i_gid = cifs_sb->mnt_gid; | ||
608 | } | ||
609 | |||
591 | /* can not call macro FreeXid here since in a void func */ | 610 | /* can not call macro FreeXid here since in a void func */ |
592 | _FreeXid(xid); | 611 | _FreeXid(xid); |
593 | } | 612 | } |
@@ -919,18 +938,25 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) | |||
919 | goto mkdir_out; | 938 | goto mkdir_out; |
920 | } | 939 | } |
921 | 940 | ||
941 | mode &= ~current->fs->umask; | ||
922 | rc = CIFSPOSIXCreate(xid, pTcon, SMB_O_DIRECTORY | SMB_O_CREAT, | 942 | rc = CIFSPOSIXCreate(xid, pTcon, SMB_O_DIRECTORY | SMB_O_CREAT, |
923 | mode, NULL /* netfid */, pInfo, &oplock, | 943 | mode, NULL /* netfid */, pInfo, &oplock, |
924 | full_path, cifs_sb->local_nls, | 944 | full_path, cifs_sb->local_nls, |
925 | cifs_sb->mnt_cifs_flags & | 945 | cifs_sb->mnt_cifs_flags & |
926 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 946 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
927 | if (rc) { | 947 | if (rc == -EOPNOTSUPP) { |
948 | kfree(pInfo); | ||
949 | goto mkdir_retry_old; | ||
950 | } else if (rc) { | ||
928 | cFYI(1, ("posix mkdir returned 0x%x", rc)); | 951 | cFYI(1, ("posix mkdir returned 0x%x", rc)); |
929 | d_drop(direntry); | 952 | d_drop(direntry); |
930 | } else { | 953 | } else { |
931 | int obj_type; | 954 | int obj_type; |
932 | if (pInfo->Type == -1) /* no return info - go query */ | 955 | if (pInfo->Type == cpu_to_le32(-1)) { |
956 | /* no return info, go query for it */ | ||
957 | kfree(pInfo); | ||
933 | goto mkdir_get_info; | 958 | goto mkdir_get_info; |
959 | } | ||
934 | /*BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if need | 960 | /*BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if need |
935 | to set uid/gid */ | 961 | to set uid/gid */ |
936 | inc_nlink(inode); | 962 | inc_nlink(inode); |
@@ -940,8 +966,10 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) | |||
940 | direntry->d_op = &cifs_dentry_ops; | 966 | direntry->d_op = &cifs_dentry_ops; |
941 | 967 | ||
942 | newinode = new_inode(inode->i_sb); | 968 | newinode = new_inode(inode->i_sb); |
943 | if (newinode == NULL) | 969 | if (newinode == NULL) { |
970 | kfree(pInfo); | ||
944 | goto mkdir_get_info; | 971 | goto mkdir_get_info; |
972 | } | ||
945 | /* Is an i_ino of zero legal? */ | 973 | /* Is an i_ino of zero legal? */ |
946 | /* Are there sanity checks we can use to ensure that | 974 | /* Are there sanity checks we can use to ensure that |
947 | the server is really filling in that field? */ | 975 | the server is really filling in that field? */ |
@@ -972,7 +1000,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) | |||
972 | kfree(pInfo); | 1000 | kfree(pInfo); |
973 | goto mkdir_out; | 1001 | goto mkdir_out; |
974 | } | 1002 | } |
975 | 1003 | mkdir_retry_old: | |
976 | /* BB add setting the equivalent of mode via CreateX w/ACLs */ | 1004 | /* BB add setting the equivalent of mode via CreateX w/ACLs */ |
977 | rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls, | 1005 | rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls, |
978 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 1006 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); |
@@ -1205,7 +1233,7 @@ cifs_rename_exit: | |||
1205 | int cifs_revalidate(struct dentry *direntry) | 1233 | int cifs_revalidate(struct dentry *direntry) |
1206 | { | 1234 | { |
1207 | int xid; | 1235 | int xid; |
1208 | int rc = 0; | 1236 | int rc = 0, wbrc = 0; |
1209 | char *full_path; | 1237 | char *full_path; |
1210 | struct cifs_sb_info *cifs_sb; | 1238 | struct cifs_sb_info *cifs_sb; |
1211 | struct cifsInodeInfo *cifsInode; | 1239 | struct cifsInodeInfo *cifsInode; |
@@ -1305,7 +1333,9 @@ int cifs_revalidate(struct dentry *direntry) | |||
1305 | if (direntry->d_inode->i_mapping) { | 1333 | if (direntry->d_inode->i_mapping) { |
1306 | /* do we need to lock inode until after invalidate completes | 1334 | /* do we need to lock inode until after invalidate completes |
1307 | below? */ | 1335 | below? */ |
1308 | filemap_fdatawrite(direntry->d_inode->i_mapping); | 1336 | wbrc = filemap_fdatawrite(direntry->d_inode->i_mapping); |
1337 | if (wbrc) | ||
1338 | CIFS_I(direntry->d_inode)->write_behind_rc = wbrc; | ||
1309 | } | 1339 | } |
1310 | if (invalidate_inode) { | 1340 | if (invalidate_inode) { |
1311 | /* shrink_dcache not necessary now that cifs dentry ops | 1341 | /* shrink_dcache not necessary now that cifs dentry ops |
@@ -1314,7 +1344,9 @@ int cifs_revalidate(struct dentry *direntry) | |||
1314 | shrink_dcache_parent(direntry); */ | 1344 | shrink_dcache_parent(direntry); */ |
1315 | if (S_ISREG(direntry->d_inode->i_mode)) { | 1345 | if (S_ISREG(direntry->d_inode->i_mode)) { |
1316 | if (direntry->d_inode->i_mapping) | 1346 | if (direntry->d_inode->i_mapping) |
1317 | filemap_fdatawait(direntry->d_inode->i_mapping); | 1347 | wbrc = filemap_fdatawait(direntry->d_inode->i_mapping); |
1348 | if (wbrc) | ||
1349 | CIFS_I(direntry->d_inode)->write_behind_rc = wbrc; | ||
1318 | /* may eventually have to do this for open files too */ | 1350 | /* may eventually have to do this for open files too */ |
1319 | if (list_empty(&(cifsInode->openFileList))) { | 1351 | if (list_empty(&(cifsInode->openFileList))) { |
1320 | /* changed on server - flush read ahead pages */ | 1352 | /* changed on server - flush read ahead pages */ |
@@ -1377,8 +1409,17 @@ static int cifs_vmtruncate(struct inode *inode, loff_t offset) | |||
1377 | } | 1409 | } |
1378 | i_size_write(inode, offset); | 1410 | i_size_write(inode, offset); |
1379 | spin_unlock(&inode->i_lock); | 1411 | spin_unlock(&inode->i_lock); |
1412 | /* | ||
1413 | * unmap_mapping_range is called twice, first simply for efficiency | ||
1414 | * so that truncate_inode_pages does fewer single-page unmaps. However | ||
1415 | * after this first call, and before truncate_inode_pages finishes, | ||
1416 | * it is possible for private pages to be COWed, which remain after | ||
1417 | * truncate_inode_pages finishes, hence the second unmap_mapping_range | ||
1418 | * call must be made for correctness. | ||
1419 | */ | ||
1380 | unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1); | 1420 | unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1); |
1381 | truncate_inode_pages(mapping, offset); | 1421 | truncate_inode_pages(mapping, offset); |
1422 | unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1); | ||
1382 | goto out_truncate; | 1423 | goto out_truncate; |
1383 | 1424 | ||
1384 | do_expand: | 1425 | do_expand: |
@@ -1448,10 +1489,20 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) | |||
1448 | 1489 | ||
1449 | /* BB check if we need to refresh inode from server now ? BB */ | 1490 | /* BB check if we need to refresh inode from server now ? BB */ |
1450 | 1491 | ||
1451 | /* need to flush data before changing file size on server */ | ||
1452 | filemap_write_and_wait(direntry->d_inode->i_mapping); | ||
1453 | |||
1454 | if (attrs->ia_valid & ATTR_SIZE) { | 1492 | if (attrs->ia_valid & ATTR_SIZE) { |
1493 | /* | ||
1494 | Flush data before changing file size on server. If the | ||
1495 | flush returns error, store it to report later and continue. | ||
1496 | BB: This should be smarter. Why bother flushing pages that | ||
1497 | will be truncated anyway? Also, should we error out here if | ||
1498 | the flush returns error? | ||
1499 | */ | ||
1500 | rc = filemap_write_and_wait(direntry->d_inode->i_mapping); | ||
1501 | if (rc != 0) { | ||
1502 | CIFS_I(direntry->d_inode)->write_behind_rc = rc; | ||
1503 | rc = 0; | ||
1504 | } | ||
1505 | |||
1455 | /* To avoid spurious oplock breaks from server, in the case of | 1506 | /* To avoid spurious oplock breaks from server, in the case of |
1456 | inodes that we already have open, avoid doing path based | 1507 | inodes that we already have open, avoid doing path based |
1457 | setting of file size if we can do it by handle. | 1508 | setting of file size if we can do it by handle. |
@@ -1469,7 +1520,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) | |||
1469 | atomic_dec(&open_file->wrtPending); | 1520 | atomic_dec(&open_file->wrtPending); |
1470 | cFYI(1, ("SetFSize for attrs rc = %d", rc)); | 1521 | cFYI(1, ("SetFSize for attrs rc = %d", rc)); |
1471 | if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) { | 1522 | if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) { |
1472 | int bytes_written; | 1523 | unsigned int bytes_written; |
1473 | rc = CIFSSMBWrite(xid, pTcon, | 1524 | rc = CIFSSMBWrite(xid, pTcon, |
1474 | nfid, 0, attrs->ia_size, | 1525 | nfid, 0, attrs->ia_size, |
1475 | &bytes_written, NULL, NULL, | 1526 | &bytes_written, NULL, NULL, |
@@ -1502,7 +1553,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) | |||
1502 | cifs_sb->mnt_cifs_flags & | 1553 | cifs_sb->mnt_cifs_flags & |
1503 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 1554 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
1504 | if (rc == 0) { | 1555 | if (rc == 0) { |
1505 | int bytes_written; | 1556 | unsigned int bytes_written; |
1506 | rc = CIFSSMBWrite(xid, pTcon, | 1557 | rc = CIFSSMBWrite(xid, pTcon, |
1507 | netfid, 0, | 1558 | netfid, 0, |
1508 | attrs->ia_size, | 1559 | attrs->ia_size, |
diff --git a/fs/cifs/link.c b/fs/cifs/link.c index 6a85ef7b8797..11f265726db7 100644 --- a/fs/cifs/link.c +++ b/fs/cifs/link.c | |||
@@ -237,7 +237,7 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen) | |||
237 | char *tmp_path = NULL; | 237 | char *tmp_path = NULL; |
238 | char *tmpbuffer; | 238 | char *tmpbuffer; |
239 | unsigned char *referrals = NULL; | 239 | unsigned char *referrals = NULL; |
240 | int num_referrals = 0; | 240 | unsigned int num_referrals = 0; |
241 | int len; | 241 | int len; |
242 | __u16 fid; | 242 | __u16 fid; |
243 | 243 | ||
diff --git a/fs/cifs/md5.c b/fs/cifs/md5.c index e5c3e1212697..f13f96d42fcf 100644 --- a/fs/cifs/md5.c +++ b/fs/cifs/md5.c | |||
@@ -276,8 +276,8 @@ hmac_md5_init_rfc2104(unsigned char *key, int key_len, | |||
276 | } | 276 | } |
277 | 277 | ||
278 | /* start out by storing key in pads */ | 278 | /* start out by storing key in pads */ |
279 | memset(ctx->k_ipad, 0, sizeof (ctx->k_ipad)); | 279 | memset(ctx->k_ipad, 0, sizeof(ctx->k_ipad)); |
280 | memset(ctx->k_opad, 0, sizeof (ctx->k_opad)); | 280 | memset(ctx->k_opad, 0, sizeof(ctx->k_opad)); |
281 | memcpy(ctx->k_ipad, key, key_len); | 281 | memcpy(ctx->k_ipad, key, key_len); |
282 | memcpy(ctx->k_opad, key, key_len); | 282 | memcpy(ctx->k_opad, key, key_len); |
283 | 283 | ||
@@ -307,8 +307,8 @@ hmac_md5_init_limK_to_64(const unsigned char *key, int key_len, | |||
307 | } | 307 | } |
308 | 308 | ||
309 | /* start out by storing key in pads */ | 309 | /* start out by storing key in pads */ |
310 | memset(ctx->k_ipad, 0, sizeof (ctx->k_ipad)); | 310 | memset(ctx->k_ipad, 0, sizeof(ctx->k_ipad)); |
311 | memset(ctx->k_opad, 0, sizeof (ctx->k_opad)); | 311 | memset(ctx->k_opad, 0, sizeof(ctx->k_opad)); |
312 | memcpy(ctx->k_ipad, key, key_len); | 312 | memcpy(ctx->k_ipad, key, key_len); |
313 | memcpy(ctx->k_opad, key, key_len); | 313 | memcpy(ctx->k_opad, key, key_len); |
314 | 314 | ||
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index 0bcec0844bee..15546c2354c5 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c | |||
@@ -73,7 +73,7 @@ sesInfoAlloc(void) | |||
73 | { | 73 | { |
74 | struct cifsSesInfo *ret_buf; | 74 | struct cifsSesInfo *ret_buf; |
75 | 75 | ||
76 | ret_buf = kzalloc(sizeof (struct cifsSesInfo), GFP_KERNEL); | 76 | ret_buf = kzalloc(sizeof(struct cifsSesInfo), GFP_KERNEL); |
77 | if (ret_buf) { | 77 | if (ret_buf) { |
78 | write_lock(&GlobalSMBSeslock); | 78 | write_lock(&GlobalSMBSeslock); |
79 | atomic_inc(&sesInfoAllocCount); | 79 | atomic_inc(&sesInfoAllocCount); |
@@ -109,7 +109,7 @@ struct cifsTconInfo * | |||
109 | tconInfoAlloc(void) | 109 | tconInfoAlloc(void) |
110 | { | 110 | { |
111 | struct cifsTconInfo *ret_buf; | 111 | struct cifsTconInfo *ret_buf; |
112 | ret_buf = kzalloc(sizeof (struct cifsTconInfo), GFP_KERNEL); | 112 | ret_buf = kzalloc(sizeof(struct cifsTconInfo), GFP_KERNEL); |
113 | if (ret_buf) { | 113 | if (ret_buf) { |
114 | write_lock(&GlobalSMBSeslock); | 114 | write_lock(&GlobalSMBSeslock); |
115 | atomic_inc(&tconInfoAllocCount); | 115 | atomic_inc(&tconInfoAllocCount); |
@@ -169,7 +169,6 @@ cifs_buf_get(void) | |||
169 | void | 169 | void |
170 | cifs_buf_release(void *buf_to_free) | 170 | cifs_buf_release(void *buf_to_free) |
171 | { | 171 | { |
172 | |||
173 | if (buf_to_free == NULL) { | 172 | if (buf_to_free == NULL) { |
174 | /* cFYI(1, ("Null buffer passed to cifs_buf_release"));*/ | 173 | /* cFYI(1, ("Null buffer passed to cifs_buf_release"));*/ |
175 | return; | 174 | return; |
@@ -299,7 +298,7 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ , | |||
299 | memset(temp, 0, 256); /* bigger than MAX_CIFS_HDR_SIZE */ | 298 | memset(temp, 0, 256); /* bigger than MAX_CIFS_HDR_SIZE */ |
300 | 299 | ||
301 | buffer->smb_buf_length = | 300 | buffer->smb_buf_length = |
302 | (2 * word_count) + sizeof (struct smb_hdr) - | 301 | (2 * word_count) + sizeof(struct smb_hdr) - |
303 | 4 /* RFC 1001 length field does not count */ + | 302 | 4 /* RFC 1001 length field does not count */ + |
304 | 2 /* for bcc field itself */ ; | 303 | 2 /* for bcc field itself */ ; |
305 | /* Note that this is the only network field that has to be converted | 304 | /* Note that this is the only network field that has to be converted |
@@ -423,8 +422,8 @@ checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length) | |||
423 | __u32 clc_len; /* calculated length */ | 422 | __u32 clc_len; /* calculated length */ |
424 | cFYI(0, ("checkSMB Length: 0x%x, smb_buf_length: 0x%x", length, len)); | 423 | cFYI(0, ("checkSMB Length: 0x%x, smb_buf_length: 0x%x", length, len)); |
425 | 424 | ||
426 | if (length < 2 + sizeof (struct smb_hdr)) { | 425 | if (length < 2 + sizeof(struct smb_hdr)) { |
427 | if ((length >= sizeof (struct smb_hdr) - 1) | 426 | if ((length >= sizeof(struct smb_hdr) - 1) |
428 | && (smb->Status.CifsError != 0)) { | 427 | && (smb->Status.CifsError != 0)) { |
429 | smb->WordCount = 0; | 428 | smb->WordCount = 0; |
430 | /* some error cases do not return wct and bcc */ | 429 | /* some error cases do not return wct and bcc */ |
diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c index 2bfed3f45d0f..646e1f06941b 100644 --- a/fs/cifs/netmisc.c +++ b/fs/cifs/netmisc.c | |||
@@ -114,10 +114,16 @@ static const struct smb_to_posix_error mapping_table_ERRSRV[] = { | |||
114 | {ERRusempx, -EIO}, | 114 | {ERRusempx, -EIO}, |
115 | {ERRusestd, -EIO}, | 115 | {ERRusestd, -EIO}, |
116 | {ERR_NOTIFY_ENUM_DIR, -ENOBUFS}, | 116 | {ERR_NOTIFY_ENUM_DIR, -ENOBUFS}, |
117 | {ERRaccountexpired, -EACCES}, | 117 | {ERRnoSuchUser, -EACCES}, |
118 | /* {ERRaccountexpired, -EACCES}, | ||
118 | {ERRbadclient, -EACCES}, | 119 | {ERRbadclient, -EACCES}, |
119 | {ERRbadLogonTime, -EACCES}, | 120 | {ERRbadLogonTime, -EACCES}, |
120 | {ERRpasswordExpired, -EACCES}, | 121 | {ERRpasswordExpired, -EACCES},*/ |
122 | {ERRaccountexpired, -EKEYEXPIRED}, | ||
123 | {ERRbadclient, -EACCES}, | ||
124 | {ERRbadLogonTime, -EACCES}, | ||
125 | {ERRpasswordExpired, -EKEYEXPIRED}, | ||
126 | |||
121 | {ERRnosupport, -EINVAL}, | 127 | {ERRnosupport, -EINVAL}, |
122 | {0, 0} | 128 | {0, 0} |
123 | }; | 129 | }; |
@@ -126,6 +132,34 @@ static const struct smb_to_posix_error mapping_table_ERRHRD[] = { | |||
126 | {0, 0} | 132 | {0, 0} |
127 | }; | 133 | }; |
128 | 134 | ||
135 | |||
136 | /* if the mount helper is missing we need to reverse the 1st slash | ||
137 | from '/' to backslash in order to format the UNC properly for | ||
138 | ip address parsing and for tree connect (unless the user | ||
139 | remembered to put the UNC name in properly). Fortunately we do | ||
140 | not have to call this twice (we check for IPv4 addresses | ||
141 | first, so it is already converted by the time we | ||
142 | try IPv6 addresses */ | ||
143 | static int canonicalize_unc(char *cp) | ||
144 | { | ||
145 | int i; | ||
146 | |||
147 | for (i = 0; i <= 46 /* INET6_ADDRSTRLEN */ ; i++) { | ||
148 | if (cp[i] == 0) | ||
149 | break; | ||
150 | if (cp[i] == '\\') | ||
151 | break; | ||
152 | if (cp[i] == '/') { | ||
153 | #ifdef CONFIG_CIFS_DEBUG2 | ||
154 | cFYI(1, ("change slash to backslash in malformed UNC")); | ||
155 | #endif | ||
156 | cp[i] = '\\'; | ||
157 | return 1; | ||
158 | } | ||
159 | } | ||
160 | return 0; | ||
161 | } | ||
162 | |||
129 | /* Convert string containing dotted ip address to binary form */ | 163 | /* Convert string containing dotted ip address to binary form */ |
130 | /* returns 0 if invalid address */ | 164 | /* returns 0 if invalid address */ |
131 | 165 | ||
@@ -135,11 +169,13 @@ cifs_inet_pton(int address_family, char *cp, void *dst) | |||
135 | int ret = 0; | 169 | int ret = 0; |
136 | 170 | ||
137 | /* calculate length by finding first slash or NULL */ | 171 | /* calculate length by finding first slash or NULL */ |
138 | /* BB Should we convert '/' slash to '\' here since it seems already | 172 | if (address_family == AF_INET) { |
139 | * done before this */ | 173 | ret = in4_pton(cp, -1 /* len */, dst, '\\', NULL); |
140 | if ( address_family == AF_INET ) { | 174 | if (ret == 0) { |
141 | ret = in4_pton(cp, -1 /* len */, dst , '\\', NULL); | 175 | if (canonicalize_unc(cp)) |
142 | } else if ( address_family == AF_INET6 ) { | 176 | ret = in4_pton(cp, -1, dst, '\\', NULL); |
177 | } | ||
178 | } else if (address_family == AF_INET6) { | ||
143 | ret = in6_pton(cp, -1 /* len */, dst , '\\', NULL); | 179 | ret = in6_pton(cp, -1 /* len */, dst , '\\', NULL); |
144 | } | 180 | } |
145 | #ifdef CONFIG_CIFS_DEBUG2 | 181 | #ifdef CONFIG_CIFS_DEBUG2 |
@@ -270,7 +306,7 @@ static const struct { | |||
270 | from NT_STATUS_NO_SUCH_USER to NT_STATUS_LOGON_FAILURE | 306 | from NT_STATUS_NO_SUCH_USER to NT_STATUS_LOGON_FAILURE |
271 | during the session setup } */ | 307 | during the session setup } */ |
272 | { | 308 | { |
273 | ERRDOS, ERRnoaccess, NT_STATUS_NO_SUCH_USER}, { | 309 | ERRDOS, ERRnoaccess, NT_STATUS_NO_SUCH_USER}, { /* could map to 2238 */ |
274 | ERRHRD, ERRgeneral, NT_STATUS_GROUP_EXISTS}, { | 310 | ERRHRD, ERRgeneral, NT_STATUS_GROUP_EXISTS}, { |
275 | ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_GROUP}, { | 311 | ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_GROUP}, { |
276 | ERRHRD, ERRgeneral, NT_STATUS_MEMBER_IN_GROUP}, { | 312 | ERRHRD, ERRgeneral, NT_STATUS_MEMBER_IN_GROUP}, { |
@@ -285,10 +321,10 @@ static const struct { | |||
285 | ERRHRD, ERRgeneral, NT_STATUS_PASSWORD_RESTRICTION}, { | 321 | ERRHRD, ERRgeneral, NT_STATUS_PASSWORD_RESTRICTION}, { |
286 | ERRDOS, ERRnoaccess, NT_STATUS_LOGON_FAILURE}, { | 322 | ERRDOS, ERRnoaccess, NT_STATUS_LOGON_FAILURE}, { |
287 | ERRHRD, ERRgeneral, NT_STATUS_ACCOUNT_RESTRICTION}, { | 323 | ERRHRD, ERRgeneral, NT_STATUS_ACCOUNT_RESTRICTION}, { |
288 | ERRSRV, 2241, NT_STATUS_INVALID_LOGON_HOURS}, { | 324 | ERRSRV, ERRbadLogonTime, NT_STATUS_INVALID_LOGON_HOURS}, { |
289 | ERRSRV, 2240, NT_STATUS_INVALID_WORKSTATION}, { | 325 | ERRSRV, ERRbadclient, NT_STATUS_INVALID_WORKSTATION}, { |
290 | ERRSRV, ERRpasswordExpired, NT_STATUS_PASSWORD_EXPIRED}, { | 326 | ERRSRV, ERRpasswordExpired, NT_STATUS_PASSWORD_EXPIRED}, { |
291 | ERRSRV, 2239, NT_STATUS_ACCOUNT_DISABLED}, { | 327 | ERRSRV, ERRaccountexpired, NT_STATUS_ACCOUNT_DISABLED}, { |
292 | ERRHRD, ERRgeneral, NT_STATUS_NONE_MAPPED}, { | 328 | ERRHRD, ERRgeneral, NT_STATUS_NONE_MAPPED}, { |
293 | ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_LUIDS_REQUESTED}, { | 329 | ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_LUIDS_REQUESTED}, { |
294 | ERRHRD, ERRgeneral, NT_STATUS_LUIDS_EXHAUSTED}, { | 330 | ERRHRD, ERRgeneral, NT_STATUS_LUIDS_EXHAUSTED}, { |
@@ -585,7 +621,7 @@ static const struct { | |||
585 | ERRDOS, ERRnoaccess, NT_STATUS_TRUST_FAILURE}, { | 621 | ERRDOS, ERRnoaccess, NT_STATUS_TRUST_FAILURE}, { |
586 | ERRHRD, ERRgeneral, NT_STATUS_MUTANT_LIMIT_EXCEEDED}, { | 622 | ERRHRD, ERRgeneral, NT_STATUS_MUTANT_LIMIT_EXCEEDED}, { |
587 | ERRDOS, ERRnetlogonNotStarted, NT_STATUS_NETLOGON_NOT_STARTED}, { | 623 | ERRDOS, ERRnetlogonNotStarted, NT_STATUS_NETLOGON_NOT_STARTED}, { |
588 | ERRSRV, 2239, NT_STATUS_ACCOUNT_EXPIRED}, { | 624 | ERRSRV, ERRaccountexpired, NT_STATUS_ACCOUNT_EXPIRED}, { |
589 | ERRHRD, ERRgeneral, NT_STATUS_POSSIBLE_DEADLOCK}, { | 625 | ERRHRD, ERRgeneral, NT_STATUS_POSSIBLE_DEADLOCK}, { |
590 | ERRHRD, ERRgeneral, NT_STATUS_NETWORK_CREDENTIAL_CONFLICT}, { | 626 | ERRHRD, ERRgeneral, NT_STATUS_NETWORK_CREDENTIAL_CONFLICT}, { |
591 | ERRHRD, ERRgeneral, NT_STATUS_REMOTE_SESSION_LIMIT}, { | 627 | ERRHRD, ERRgeneral, NT_STATUS_REMOTE_SESSION_LIMIT}, { |
@@ -734,7 +770,7 @@ cifs_print_status(__u32 status_code) | |||
734 | 770 | ||
735 | 771 | ||
736 | static void | 772 | static void |
737 | ntstatus_to_dos(__u32 ntstatus, __u8 * eclass, __u16 * ecode) | 773 | ntstatus_to_dos(__u32 ntstatus, __u8 *eclass, __u16 *ecode) |
738 | { | 774 | { |
739 | int i; | 775 | int i; |
740 | if (ntstatus == 0) { | 776 | if (ntstatus == 0) { |
@@ -754,7 +790,7 @@ ntstatus_to_dos(__u32 ntstatus, __u8 * eclass, __u16 * ecode) | |||
754 | } | 790 | } |
755 | 791 | ||
756 | int | 792 | int |
757 | map_smb_to_linux_error(struct smb_hdr *smb) | 793 | map_smb_to_linux_error(struct smb_hdr *smb, int logErr) |
758 | { | 794 | { |
759 | unsigned int i; | 795 | unsigned int i; |
760 | int rc = -EIO; /* if transport error smb error may not be set */ | 796 | int rc = -EIO; /* if transport error smb error may not be set */ |
@@ -771,7 +807,9 @@ map_smb_to_linux_error(struct smb_hdr *smb) | |||
771 | /* translate the newer STATUS codes to old style SMB errors | 807 | /* translate the newer STATUS codes to old style SMB errors |
772 | * and then to POSIX errors */ | 808 | * and then to POSIX errors */ |
773 | __u32 err = le32_to_cpu(smb->Status.CifsError); | 809 | __u32 err = le32_to_cpu(smb->Status.CifsError); |
774 | if (cifsFYI & CIFS_RC) | 810 | if (logErr && (err != (NT_STATUS_MORE_PROCESSING_REQUIRED))) |
811 | cifs_print_status(err); | ||
812 | else if (cifsFYI & CIFS_RC) | ||
775 | cifs_print_status(err); | 813 | cifs_print_status(err); |
776 | ntstatus_to_dos(err, &smberrclass, &smberrcode); | 814 | ntstatus_to_dos(err, &smberrclass, &smberrcode); |
777 | } else { | 815 | } else { |
@@ -785,8 +823,8 @@ map_smb_to_linux_error(struct smb_hdr *smb) | |||
785 | if (smberrclass == ERRDOS) { /* 1 byte field no need to byte reverse */ | 823 | if (smberrclass == ERRDOS) { /* 1 byte field no need to byte reverse */ |
786 | for (i = 0; | 824 | for (i = 0; |
787 | i < | 825 | i < |
788 | sizeof (mapping_table_ERRDOS) / | 826 | sizeof(mapping_table_ERRDOS) / |
789 | sizeof (struct smb_to_posix_error); i++) { | 827 | sizeof(struct smb_to_posix_error); i++) { |
790 | if (mapping_table_ERRDOS[i].smb_err == 0) | 828 | if (mapping_table_ERRDOS[i].smb_err == 0) |
791 | break; | 829 | break; |
792 | else if (mapping_table_ERRDOS[i].smb_err == | 830 | else if (mapping_table_ERRDOS[i].smb_err == |
@@ -799,8 +837,8 @@ map_smb_to_linux_error(struct smb_hdr *smb) | |||
799 | } else if (smberrclass == ERRSRV) { /* server class of error codes */ | 837 | } else if (smberrclass == ERRSRV) { /* server class of error codes */ |
800 | for (i = 0; | 838 | for (i = 0; |
801 | i < | 839 | i < |
802 | sizeof (mapping_table_ERRSRV) / | 840 | sizeof(mapping_table_ERRSRV) / |
803 | sizeof (struct smb_to_posix_error); i++) { | 841 | sizeof(struct smb_to_posix_error); i++) { |
804 | if (mapping_table_ERRSRV[i].smb_err == 0) | 842 | if (mapping_table_ERRSRV[i].smb_err == 0) |
805 | break; | 843 | break; |
806 | else if (mapping_table_ERRSRV[i].smb_err == | 844 | else if (mapping_table_ERRSRV[i].smb_err == |
@@ -813,7 +851,7 @@ map_smb_to_linux_error(struct smb_hdr *smb) | |||
813 | } | 851 | } |
814 | /* else ERRHRD class errors or junk - return EIO */ | 852 | /* else ERRHRD class errors or junk - return EIO */ |
815 | 853 | ||
816 | cFYI(1, (" !!Mapping smb error code %d to POSIX err %d !!", | 854 | cFYI(1, ("Mapping smb error code %d to POSIX err %d", |
817 | smberrcode, rc)); | 855 | smberrcode, rc)); |
818 | 856 | ||
819 | /* generic corrective action e.g. reconnect SMB session on | 857 | /* generic corrective action e.g. reconnect SMB session on |
@@ -829,14 +867,14 @@ map_smb_to_linux_error(struct smb_hdr *smb) | |||
829 | unsigned int | 867 | unsigned int |
830 | smbCalcSize(struct smb_hdr *ptr) | 868 | smbCalcSize(struct smb_hdr *ptr) |
831 | { | 869 | { |
832 | return (sizeof (struct smb_hdr) + (2 * ptr->WordCount) + | 870 | return (sizeof(struct smb_hdr) + (2 * ptr->WordCount) + |
833 | 2 /* size of the bcc field */ + BCC(ptr)); | 871 | 2 /* size of the bcc field */ + BCC(ptr)); |
834 | } | 872 | } |
835 | 873 | ||
836 | unsigned int | 874 | unsigned int |
837 | smbCalcSize_LE(struct smb_hdr *ptr) | 875 | smbCalcSize_LE(struct smb_hdr *ptr) |
838 | { | 876 | { |
839 | return (sizeof (struct smb_hdr) + (2 * ptr->WordCount) + | 877 | return (sizeof(struct smb_hdr) + (2 * ptr->WordCount) + |
840 | 2 /* size of the bcc field */ + le16_to_cpu(BCC_LE(ptr))); | 878 | 2 /* size of the bcc field */ + le16_to_cpu(BCC_LE(ptr))); |
841 | } | 879 | } |
842 | 880 | ||
@@ -899,8 +937,11 @@ struct timespec cnvrtDosUnixTm(__u16 date, __u16 time) | |||
899 | cERROR(1, ("illegal hours %d", st->Hours)); | 937 | cERROR(1, ("illegal hours %d", st->Hours)); |
900 | days = sd->Day; | 938 | days = sd->Day; |
901 | month = sd->Month; | 939 | month = sd->Month; |
902 | if ((days > 31) || (month > 12)) | 940 | if ((days > 31) || (month > 12)) { |
903 | cERROR(1, ("illegal date, month %d day: %d", month, days)); | 941 | cERROR(1, ("illegal date, month %d day: %d", month, days)); |
942 | if (month > 12) | ||
943 | month = 12; | ||
944 | } | ||
904 | month -= 1; | 945 | month -= 1; |
905 | days += total_days_of_prev_months[month]; | 946 | days += total_days_of_prev_months[month]; |
906 | days += 3652; /* account for difference in days between 1980 and 1970 */ | 947 | days += 3652; /* account for difference in days between 1980 and 1970 */ |
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index 916df9431336..0f22def4bdff 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c | |||
@@ -121,7 +121,7 @@ static void AdjustForTZ(struct cifsTconInfo *tcon, struct inode *inode) | |||
121 | 121 | ||
122 | 122 | ||
123 | static void fill_in_inode(struct inode *tmp_inode, int new_buf_type, | 123 | static void fill_in_inode(struct inode *tmp_inode, int new_buf_type, |
124 | char *buf, int *pobject_type, int isNewInode) | 124 | char *buf, unsigned int *pobject_type, int isNewInode) |
125 | { | 125 | { |
126 | loff_t local_size; | 126 | loff_t local_size; |
127 | struct timespec local_mtime; | 127 | struct timespec local_mtime; |
@@ -171,7 +171,13 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type, | |||
171 | /* Linux can not store file creation time unfortunately so ignore it */ | 171 | /* Linux can not store file creation time unfortunately so ignore it */ |
172 | 172 | ||
173 | cifsInfo->cifsAttrs = attr; | 173 | cifsInfo->cifsAttrs = attr; |
174 | cifsInfo->time = jiffies; | 174 | #ifdef CONFIG_CIFS_EXPERIMENTAL |
175 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { | ||
176 | /* get more accurate mode via ACL - so force inode refresh */ | ||
177 | cifsInfo->time = 0; | ||
178 | } else | ||
179 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ | ||
180 | cifsInfo->time = jiffies; | ||
175 | 181 | ||
176 | /* treat dos attribute of read-only as read-only mode bit e.g. 555? */ | 182 | /* treat dos attribute of read-only as read-only mode bit e.g. 555? */ |
177 | /* 2767 perms - indicate mandatory locking */ | 183 | /* 2767 perms - indicate mandatory locking */ |
@@ -294,7 +300,7 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type, | |||
294 | } | 300 | } |
295 | 301 | ||
296 | static void unix_fill_in_inode(struct inode *tmp_inode, | 302 | static void unix_fill_in_inode(struct inode *tmp_inode, |
297 | FILE_UNIX_INFO *pfindData, int *pobject_type, int isNewInode) | 303 | FILE_UNIX_INFO *pfindData, unsigned int *pobject_type, int isNewInode) |
298 | { | 304 | { |
299 | loff_t local_size; | 305 | loff_t local_size; |
300 | struct timespec local_mtime; | 306 | struct timespec local_mtime; |
@@ -495,7 +501,7 @@ ffirst_retry: | |||
495 | static int cifs_unicode_bytelen(char *str) | 501 | static int cifs_unicode_bytelen(char *str) |
496 | { | 502 | { |
497 | int len; | 503 | int len; |
498 | __le16 * ustr = (__le16 *)str; | 504 | __le16 *ustr = (__le16 *)str; |
499 | 505 | ||
500 | for (len = 0; len <= PATH_MAX; len++) { | 506 | for (len = 0; len <= PATH_MAX; len++) { |
501 | if (ustr[len] == 0) | 507 | if (ustr[len] == 0) |
@@ -826,7 +832,7 @@ static int cifs_filldir(char *pfindEntry, struct file *file, | |||
826 | int rc = 0; | 832 | int rc = 0; |
827 | struct qstr qstring; | 833 | struct qstr qstring; |
828 | struct cifsFileInfo *pCifsF; | 834 | struct cifsFileInfo *pCifsF; |
829 | unsigned obj_type; | 835 | unsigned int obj_type; |
830 | ino_t inum; | 836 | ino_t inum; |
831 | struct cifs_sb_info *cifs_sb; | 837 | struct cifs_sb_info *cifs_sb; |
832 | struct inode *tmp_inode; | 838 | struct inode *tmp_inode; |
@@ -1067,7 +1073,7 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir) | |||
1067 | for (i = 0; (i < num_to_fill) && (rc == 0); i++) { | 1073 | for (i = 0; (i < num_to_fill) && (rc == 0); i++) { |
1068 | if (current_entry == NULL) { | 1074 | if (current_entry == NULL) { |
1069 | /* evaluate whether this case is an error */ | 1075 | /* evaluate whether this case is an error */ |
1070 | cERROR(1,("past end of SMB num to fill %d i %d", | 1076 | cERROR(1, ("past SMB end, num to fill %d i %d", |
1071 | num_to_fill, i)); | 1077 | num_to_fill, i)); |
1072 | break; | 1078 | break; |
1073 | } | 1079 | } |
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c index 892be9b4d1f3..d0cb469daab7 100644 --- a/fs/cifs/sess.c +++ b/fs/cifs/sess.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include "ntlmssp.h" | 29 | #include "ntlmssp.h" |
30 | #include "nterr.h" | 30 | #include "nterr.h" |
31 | #include <linux/utsname.h> | 31 | #include <linux/utsname.h> |
32 | #include "cifs_spnego.h" | ||
32 | 33 | ||
33 | extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8, | 34 | extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8, |
34 | unsigned char *p24); | 35 | unsigned char *p24); |
@@ -67,14 +68,59 @@ static __u32 cifs_ssetup_hdr(struct cifsSesInfo *ses, SESSION_SETUP_ANDX *pSMB) | |||
67 | pSMB->req.hdr.Flags2 |= SMBFLG2_DFS; | 68 | pSMB->req.hdr.Flags2 |= SMBFLG2_DFS; |
68 | capabilities |= CAP_DFS; | 69 | capabilities |= CAP_DFS; |
69 | } | 70 | } |
70 | if (ses->capabilities & CAP_UNIX) { | 71 | if (ses->capabilities & CAP_UNIX) |
71 | capabilities |= CAP_UNIX; | 72 | capabilities |= CAP_UNIX; |
72 | } | ||
73 | 73 | ||
74 | /* BB check whether to init vcnum BB */ | 74 | /* BB check whether to init vcnum BB */ |
75 | return capabilities; | 75 | return capabilities; |
76 | } | 76 | } |
77 | 77 | ||
78 | static void | ||
79 | unicode_oslm_strings(char **pbcc_area, const struct nls_table *nls_cp) | ||
80 | { | ||
81 | char *bcc_ptr = *pbcc_area; | ||
82 | int bytes_ret = 0; | ||
83 | |||
84 | /* Copy OS version */ | ||
85 | bytes_ret = cifs_strtoUCS((__le16 *)bcc_ptr, "Linux version ", 32, | ||
86 | nls_cp); | ||
87 | bcc_ptr += 2 * bytes_ret; | ||
88 | bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, init_utsname()->release, | ||
89 | 32, nls_cp); | ||
90 | bcc_ptr += 2 * bytes_ret; | ||
91 | bcc_ptr += 2; /* trailing null */ | ||
92 | |||
93 | bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS, | ||
94 | 32, nls_cp); | ||
95 | bcc_ptr += 2 * bytes_ret; | ||
96 | bcc_ptr += 2; /* trailing null */ | ||
97 | |||
98 | *pbcc_area = bcc_ptr; | ||
99 | } | ||
100 | |||
101 | static void unicode_domain_string(char **pbcc_area, struct cifsSesInfo *ses, | ||
102 | const struct nls_table *nls_cp) | ||
103 | { | ||
104 | char *bcc_ptr = *pbcc_area; | ||
105 | int bytes_ret = 0; | ||
106 | |||
107 | /* copy domain */ | ||
108 | if (ses->domainName == NULL) { | ||
109 | /* Sending null domain better than using a bogus domain name (as | ||
110 | we did briefly in 2.6.18) since server will use its default */ | ||
111 | *bcc_ptr = 0; | ||
112 | *(bcc_ptr+1) = 0; | ||
113 | bytes_ret = 0; | ||
114 | } else | ||
115 | bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, ses->domainName, | ||
116 | 256, nls_cp); | ||
117 | bcc_ptr += 2 * bytes_ret; | ||
118 | bcc_ptr += 2; /* account for null terminator */ | ||
119 | |||
120 | *pbcc_area = bcc_ptr; | ||
121 | } | ||
122 | |||
123 | |||
78 | static void unicode_ssetup_strings(char **pbcc_area, struct cifsSesInfo *ses, | 124 | static void unicode_ssetup_strings(char **pbcc_area, struct cifsSesInfo *ses, |
79 | const struct nls_table *nls_cp) | 125 | const struct nls_table *nls_cp) |
80 | { | 126 | { |
@@ -100,32 +146,9 @@ static void unicode_ssetup_strings(char **pbcc_area, struct cifsSesInfo *ses, | |||
100 | } | 146 | } |
101 | bcc_ptr += 2 * bytes_ret; | 147 | bcc_ptr += 2 * bytes_ret; |
102 | bcc_ptr += 2; /* account for null termination */ | 148 | bcc_ptr += 2; /* account for null termination */ |
103 | /* copy domain */ | ||
104 | if (ses->domainName == NULL) { | ||
105 | /* Sending null domain better than using a bogus domain name (as | ||
106 | we did briefly in 2.6.18) since server will use its default */ | ||
107 | *bcc_ptr = 0; | ||
108 | *(bcc_ptr+1) = 0; | ||
109 | bytes_ret = 0; | ||
110 | } else | ||
111 | bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, ses->domainName, | ||
112 | 256, nls_cp); | ||
113 | bcc_ptr += 2 * bytes_ret; | ||
114 | bcc_ptr += 2; /* account for null terminator */ | ||
115 | 149 | ||
116 | /* Copy OS version */ | 150 | unicode_domain_string(&bcc_ptr, ses, nls_cp); |
117 | bytes_ret = cifs_strtoUCS((__le16 *)bcc_ptr, "Linux version ", 32, | 151 | unicode_oslm_strings(&bcc_ptr, nls_cp); |
118 | nls_cp); | ||
119 | bcc_ptr += 2 * bytes_ret; | ||
120 | bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, init_utsname()->release, | ||
121 | 32, nls_cp); | ||
122 | bcc_ptr += 2 * bytes_ret; | ||
123 | bcc_ptr += 2; /* trailing null */ | ||
124 | |||
125 | bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS, | ||
126 | 32, nls_cp); | ||
127 | bcc_ptr += 2 * bytes_ret; | ||
128 | bcc_ptr += 2; /* trailing null */ | ||
129 | 152 | ||
130 | *pbcc_area = bcc_ptr; | 153 | *pbcc_area = bcc_ptr; |
131 | } | 154 | } |
@@ -203,14 +226,11 @@ static int decode_unicode_ssetup(char **pbcc_area, int bleft, | |||
203 | if (len >= words_left) | 226 | if (len >= words_left) |
204 | return rc; | 227 | return rc; |
205 | 228 | ||
206 | if (ses->serverOS) | 229 | kfree(ses->serverOS); |
207 | kfree(ses->serverOS); | ||
208 | /* UTF-8 string will not grow more than four times as big as UCS-16 */ | 230 | /* UTF-8 string will not grow more than four times as big as UCS-16 */ |
209 | ses->serverOS = kzalloc(4 * len, GFP_KERNEL); | 231 | ses->serverOS = kzalloc(4 * len, GFP_KERNEL); |
210 | if (ses->serverOS != NULL) { | 232 | if (ses->serverOS != NULL) |
211 | cifs_strfromUCS_le(ses->serverOS, (__le16 *)data, len, | 233 | cifs_strfromUCS_le(ses->serverOS, (__le16 *)data, len, nls_cp); |
212 | nls_cp); | ||
213 | } | ||
214 | data += 2 * (len + 1); | 234 | data += 2 * (len + 1); |
215 | words_left -= len + 1; | 235 | words_left -= len + 1; |
216 | 236 | ||
@@ -220,8 +240,7 @@ static int decode_unicode_ssetup(char **pbcc_area, int bleft, | |||
220 | if (len >= words_left) | 240 | if (len >= words_left) |
221 | return rc; | 241 | return rc; |
222 | 242 | ||
223 | if (ses->serverNOS) | 243 | kfree(ses->serverNOS); |
224 | kfree(ses->serverNOS); | ||
225 | ses->serverNOS = kzalloc(4 * len, GFP_KERNEL); /* BB this is wrong length FIXME BB */ | 244 | ses->serverNOS = kzalloc(4 * len, GFP_KERNEL); /* BB this is wrong length FIXME BB */ |
226 | if (ses->serverNOS != NULL) { | 245 | if (ses->serverNOS != NULL) { |
227 | cifs_strfromUCS_le(ses->serverNOS, (__le16 *)data, len, | 246 | cifs_strfromUCS_le(ses->serverNOS, (__le16 *)data, len, |
@@ -240,8 +259,7 @@ static int decode_unicode_ssetup(char **pbcc_area, int bleft, | |||
240 | if (len > words_left) | 259 | if (len > words_left) |
241 | return rc; | 260 | return rc; |
242 | 261 | ||
243 | if (ses->serverDomain) | 262 | kfree(ses->serverDomain); |
244 | kfree(ses->serverDomain); | ||
245 | ses->serverDomain = kzalloc(2 * (len + 1), GFP_KERNEL); /* BB FIXME wrong length */ | 263 | ses->serverDomain = kzalloc(2 * (len + 1), GFP_KERNEL); /* BB FIXME wrong length */ |
246 | if (ses->serverDomain != NULL) { | 264 | if (ses->serverDomain != NULL) { |
247 | cifs_strfromUCS_le(ses->serverDomain, (__le16 *)data, len, | 265 | cifs_strfromUCS_le(ses->serverDomain, (__le16 *)data, len, |
@@ -271,8 +289,7 @@ static int decode_ascii_ssetup(char **pbcc_area, int bleft, | |||
271 | if (len >= bleft) | 289 | if (len >= bleft) |
272 | return rc; | 290 | return rc; |
273 | 291 | ||
274 | if (ses->serverOS) | 292 | kfree(ses->serverOS); |
275 | kfree(ses->serverOS); | ||
276 | 293 | ||
277 | ses->serverOS = kzalloc(len + 1, GFP_KERNEL); | 294 | ses->serverOS = kzalloc(len + 1, GFP_KERNEL); |
278 | if (ses->serverOS) | 295 | if (ses->serverOS) |
@@ -289,8 +306,7 @@ static int decode_ascii_ssetup(char **pbcc_area, int bleft, | |||
289 | if (len >= bleft) | 306 | if (len >= bleft) |
290 | return rc; | 307 | return rc; |
291 | 308 | ||
292 | if (ses->serverNOS) | 309 | kfree(ses->serverNOS); |
293 | kfree(ses->serverNOS); | ||
294 | 310 | ||
295 | ses->serverNOS = kzalloc(len + 1, GFP_KERNEL); | 311 | ses->serverNOS = kzalloc(len + 1, GFP_KERNEL); |
296 | if (ses->serverNOS) | 312 | if (ses->serverNOS) |
@@ -325,11 +341,12 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, | |||
325 | SESSION_SETUP_ANDX *pSMB; | 341 | SESSION_SETUP_ANDX *pSMB; |
326 | __u32 capabilities; | 342 | __u32 capabilities; |
327 | int count; | 343 | int count; |
328 | int resp_buf_type = 0; | 344 | int resp_buf_type; |
329 | struct kvec iov[2]; | 345 | struct kvec iov[3]; |
330 | enum securityEnum type; | 346 | enum securityEnum type; |
331 | __u16 action; | 347 | __u16 action; |
332 | int bytes_remaining; | 348 | int bytes_remaining; |
349 | struct key *spnego_key = NULL; | ||
333 | 350 | ||
334 | if (ses == NULL) | 351 | if (ses == NULL) |
335 | return -EINVAL; | 352 | return -EINVAL; |
@@ -362,24 +379,32 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, | |||
362 | 379 | ||
363 | capabilities = cifs_ssetup_hdr(ses, pSMB); | 380 | capabilities = cifs_ssetup_hdr(ses, pSMB); |
364 | 381 | ||
365 | /* we will send the SMB in two pieces, | 382 | /* we will send the SMB in three pieces: |
366 | a fixed length beginning part, and a | 383 | a fixed length beginning part, an optional |
367 | second part which will include the strings | 384 | SPNEGO blob (which can be zero length), and a |
368 | and rest of bcc area, in order to avoid having | 385 | last part which will include the strings |
369 | to do a large buffer 17K allocation */ | 386 | and rest of bcc area. This allows us to avoid |
387 | a large buffer 17K allocation */ | ||
370 | iov[0].iov_base = (char *)pSMB; | 388 | iov[0].iov_base = (char *)pSMB; |
371 | iov[0].iov_len = smb_buf->smb_buf_length + 4; | 389 | iov[0].iov_len = smb_buf->smb_buf_length + 4; |
372 | 390 | ||
391 | /* setting this here allows the code at the end of the function | ||
392 | to free the request buffer if there's an error */ | ||
393 | resp_buf_type = CIFS_SMALL_BUFFER; | ||
394 | |||
373 | /* 2000 big enough to fit max user, domain, NOS name etc. */ | 395 | /* 2000 big enough to fit max user, domain, NOS name etc. */ |
374 | str_area = kmalloc(2000, GFP_KERNEL); | 396 | str_area = kmalloc(2000, GFP_KERNEL); |
375 | if (str_area == NULL) { | 397 | if (str_area == NULL) { |
376 | cifs_small_buf_release(smb_buf); | 398 | rc = -ENOMEM; |
377 | return -ENOMEM; | 399 | goto ssetup_exit; |
378 | } | 400 | } |
379 | bcc_ptr = str_area; | 401 | bcc_ptr = str_area; |
380 | 402 | ||
381 | ses->flags &= ~CIFS_SES_LANMAN; | 403 | ses->flags &= ~CIFS_SES_LANMAN; |
382 | 404 | ||
405 | iov[1].iov_base = NULL; | ||
406 | iov[1].iov_len = 0; | ||
407 | |||
383 | if (type == LANMAN) { | 408 | if (type == LANMAN) { |
384 | #ifdef CONFIG_CIFS_WEAK_PW_HASH | 409 | #ifdef CONFIG_CIFS_WEAK_PW_HASH |
385 | char lnm_session_key[CIFS_SESS_KEY_SIZE]; | 410 | char lnm_session_key[CIFS_SESS_KEY_SIZE]; |
@@ -448,8 +473,8 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, | |||
448 | struct ntlmv2_resp */ | 473 | struct ntlmv2_resp */ |
449 | 474 | ||
450 | if (v2_sess_key == NULL) { | 475 | if (v2_sess_key == NULL) { |
451 | cifs_small_buf_release(smb_buf); | 476 | rc = -ENOMEM; |
452 | return -ENOMEM; | 477 | goto ssetup_exit; |
453 | } | 478 | } |
454 | 479 | ||
455 | pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities); | 480 | pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities); |
@@ -479,25 +504,72 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, | |||
479 | if (ses->capabilities & CAP_UNICODE) { | 504 | if (ses->capabilities & CAP_UNICODE) { |
480 | if (iov[0].iov_len % 2) { | 505 | if (iov[0].iov_len % 2) { |
481 | *bcc_ptr = 0; | 506 | *bcc_ptr = 0; |
482 | } bcc_ptr++; | 507 | bcc_ptr++; |
508 | } | ||
483 | unicode_ssetup_strings(&bcc_ptr, ses, nls_cp); | 509 | unicode_ssetup_strings(&bcc_ptr, ses, nls_cp); |
484 | } else | 510 | } else |
485 | ascii_ssetup_strings(&bcc_ptr, ses, nls_cp); | 511 | ascii_ssetup_strings(&bcc_ptr, ses, nls_cp); |
486 | } else /* NTLMSSP or SPNEGO */ { | 512 | } else if (type == Kerberos) { |
513 | #ifdef CONFIG_CIFS_UPCALL | ||
514 | struct cifs_spnego_msg *msg; | ||
515 | spnego_key = cifs_get_spnego_key(ses); | ||
516 | if (IS_ERR(spnego_key)) { | ||
517 | rc = PTR_ERR(spnego_key); | ||
518 | spnego_key = NULL; | ||
519 | goto ssetup_exit; | ||
520 | } | ||
521 | |||
522 | msg = spnego_key->payload.data; | ||
523 | /* bail out if key is too long */ | ||
524 | if (msg->sesskey_len > | ||
525 | sizeof(ses->server->mac_signing_key.data.krb5)) { | ||
526 | cERROR(1, ("Kerberos signing key too long (%u bytes)", | ||
527 | msg->sesskey_len)); | ||
528 | rc = -EOVERFLOW; | ||
529 | goto ssetup_exit; | ||
530 | } | ||
531 | ses->server->mac_signing_key.len = msg->sesskey_len; | ||
532 | memcpy(ses->server->mac_signing_key.data.krb5, msg->data, | ||
533 | msg->sesskey_len); | ||
487 | pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; | 534 | pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; |
488 | capabilities |= CAP_EXTENDED_SECURITY; | 535 | capabilities |= CAP_EXTENDED_SECURITY; |
489 | pSMB->req.Capabilities = cpu_to_le32(capabilities); | 536 | pSMB->req.Capabilities = cpu_to_le32(capabilities); |
490 | /* BB set password lengths */ | 537 | iov[1].iov_base = msg->data + msg->sesskey_len; |
538 | iov[1].iov_len = msg->secblob_len; | ||
539 | pSMB->req.SecurityBlobLength = cpu_to_le16(iov[1].iov_len); | ||
540 | |||
541 | if (ses->capabilities & CAP_UNICODE) { | ||
542 | /* unicode strings must be word aligned */ | ||
543 | if (iov[0].iov_len % 2) { | ||
544 | *bcc_ptr = 0; | ||
545 | bcc_ptr++; | ||
546 | } | ||
547 | unicode_oslm_strings(&bcc_ptr, nls_cp); | ||
548 | unicode_domain_string(&bcc_ptr, ses, nls_cp); | ||
549 | } else | ||
550 | /* BB: is this right? */ | ||
551 | ascii_ssetup_strings(&bcc_ptr, ses, nls_cp); | ||
552 | #else /* ! CONFIG_CIFS_UPCALL */ | ||
553 | cERROR(1, ("Kerberos negotiated but upcall support disabled!")); | ||
554 | rc = -ENOSYS; | ||
555 | goto ssetup_exit; | ||
556 | #endif /* CONFIG_CIFS_UPCALL */ | ||
557 | } else { | ||
558 | cERROR(1, ("secType %d not supported!", type)); | ||
559 | rc = -ENOSYS; | ||
560 | goto ssetup_exit; | ||
491 | } | 561 | } |
492 | 562 | ||
493 | count = (long) bcc_ptr - (long) str_area; | 563 | iov[2].iov_base = str_area; |
564 | iov[2].iov_len = (long) bcc_ptr - (long) str_area; | ||
565 | |||
566 | count = iov[1].iov_len + iov[2].iov_len; | ||
494 | smb_buf->smb_buf_length += count; | 567 | smb_buf->smb_buf_length += count; |
495 | 568 | ||
496 | BCC_LE(smb_buf) = cpu_to_le16(count); | 569 | BCC_LE(smb_buf) = cpu_to_le16(count); |
497 | 570 | ||
498 | iov[1].iov_base = str_area; | 571 | rc = SendReceive2(xid, ses, iov, 3 /* num_iovecs */, &resp_buf_type, |
499 | iov[1].iov_len = count; | 572 | CIFS_STD_OP /* not long */ | CIFS_LOG_ERROR); |
500 | rc = SendReceive2(xid, ses, iov, 2 /* num_iovecs */, &resp_buf_type, 0); | ||
501 | /* SMB request buf freed in SendReceive2 */ | 573 | /* SMB request buf freed in SendReceive2 */ |
502 | 574 | ||
503 | cFYI(1, ("ssetup rc from sendrecv2 is %d", rc)); | 575 | cFYI(1, ("ssetup rc from sendrecv2 is %d", rc)); |
@@ -543,6 +615,8 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, | |||
543 | ses, nls_cp); | 615 | ses, nls_cp); |
544 | 616 | ||
545 | ssetup_exit: | 617 | ssetup_exit: |
618 | if (spnego_key) | ||
619 | key_put(spnego_key); | ||
546 | kfree(str_area); | 620 | kfree(str_area); |
547 | if (resp_buf_type == CIFS_SMALL_BUFFER) { | 621 | if (resp_buf_type == CIFS_SMALL_BUFFER) { |
548 | cFYI(1, ("ssetup freeing small buf %p", iov[0].iov_base)); | 622 | cFYI(1, ("ssetup freeing small buf %p", iov[0].iov_base)); |
diff --git a/fs/cifs/smbencrypt.c b/fs/cifs/smbencrypt.c index 90542a39be17..58bbfd992cc0 100644 --- a/fs/cifs/smbencrypt.c +++ b/fs/cifs/smbencrypt.c | |||
@@ -80,7 +80,7 @@ SMBencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24) | |||
80 | 80 | ||
81 | /* Routines for Windows NT MD4 Hash functions. */ | 81 | /* Routines for Windows NT MD4 Hash functions. */ |
82 | static int | 82 | static int |
83 | _my_wcslen(__u16 * str) | 83 | _my_wcslen(__u16 *str) |
84 | { | 84 | { |
85 | int len = 0; | 85 | int len = 0; |
86 | while (*str++ != 0) | 86 | while (*str++ != 0) |
@@ -96,7 +96,7 @@ _my_wcslen(__u16 * str) | |||
96 | */ | 96 | */ |
97 | 97 | ||
98 | static int | 98 | static int |
99 | _my_mbstowcs(__u16 * dst, const unsigned char *src, int len) | 99 | _my_mbstowcs(__u16 *dst, const unsigned char *src, int len) |
100 | { /* BB not a very good conversion routine - change/fix */ | 100 | { /* BB not a very good conversion routine - change/fix */ |
101 | int i; | 101 | int i; |
102 | __u16 val; | 102 | __u16 val; |
@@ -125,9 +125,9 @@ E_md4hash(const unsigned char *passwd, unsigned char *p16) | |||
125 | /* Password cannot be longer than 128 characters */ | 125 | /* Password cannot be longer than 128 characters */ |
126 | if (passwd) { | 126 | if (passwd) { |
127 | len = strlen((char *) passwd); | 127 | len = strlen((char *) passwd); |
128 | if (len > 128) { | 128 | if (len > 128) |
129 | len = 128; | 129 | len = 128; |
130 | } | 130 | |
131 | /* Password must be converted to NT unicode */ | 131 | /* Password must be converted to NT unicode */ |
132 | _my_mbstowcs(wpwd, passwd, len); | 132 | _my_mbstowcs(wpwd, passwd, len); |
133 | } else | 133 | } else |
@@ -135,7 +135,7 @@ E_md4hash(const unsigned char *passwd, unsigned char *p16) | |||
135 | 135 | ||
136 | wpwd[len] = 0; /* Ensure string is null terminated */ | 136 | wpwd[len] = 0; /* Ensure string is null terminated */ |
137 | /* Calculate length in bytes */ | 137 | /* Calculate length in bytes */ |
138 | len = _my_wcslen(wpwd) * sizeof (__u16); | 138 | len = _my_wcslen(wpwd) * sizeof(__u16); |
139 | 139 | ||
140 | mdfour(p16, (unsigned char *) wpwd, len); | 140 | mdfour(p16, (unsigned char *) wpwd, len); |
141 | memset(wpwd, 0, 129 * 2); | 141 | memset(wpwd, 0, 129 * 2); |
@@ -167,7 +167,7 @@ nt_lm_owf_gen(char *pwd, unsigned char nt_p16[16], unsigned char p16[16]) | |||
167 | E_P16((unsigned char *) passwd, (unsigned char *) p16); | 167 | E_P16((unsigned char *) passwd, (unsigned char *) p16); |
168 | 168 | ||
169 | /* clear out local copy of user's password (just being paranoid). */ | 169 | /* clear out local copy of user's password (just being paranoid). */ |
170 | memset(passwd, '\0', sizeof (passwd)); | 170 | memset(passwd, '\0', sizeof(passwd)); |
171 | } | 171 | } |
172 | #endif | 172 | #endif |
173 | 173 | ||
@@ -189,8 +189,10 @@ ntv2_owf_gen(const unsigned char owf[16], const char *user_n, | |||
189 | return; | 189 | return; |
190 | dom_u = user_u + 1024; | 190 | dom_u = user_u + 1024; |
191 | 191 | ||
192 | /* push_ucs2(NULL, user_u, user_n, (user_l+1)*2, STR_UNICODE|STR_NOALIGN|STR_TERMINATE|STR_UPPER); | 192 | /* push_ucs2(NULL, user_u, user_n, (user_l+1)*2, |
193 | push_ucs2(NULL, dom_u, domain_n, (domain_l+1)*2, STR_UNICODE|STR_NOALIGN|STR_TERMINATE|STR_UPPER); */ | 193 | STR_UNICODE|STR_NOALIGN|STR_TERMINATE|STR_UPPER); |
194 | push_ucs2(NULL, dom_u, domain_n, (domain_l+1)*2, | ||
195 | STR_UNICODE|STR_NOALIGN|STR_TERMINATE|STR_UPPER); */ | ||
194 | 196 | ||
195 | /* BB user and domain may need to be uppercased */ | 197 | /* BB user and domain may need to be uppercased */ |
196 | user_l = cifs_strtoUCS(user_u, user_n, 511, nls_codepage); | 198 | user_l = cifs_strtoUCS(user_u, user_n, 511, nls_codepage); |
diff --git a/fs/cifs/smberr.h b/fs/cifs/smberr.h index 2ef0be288820..7f50e8577c1c 100644 --- a/fs/cifs/smberr.h +++ b/fs/cifs/smberr.h | |||
@@ -173,9 +173,10 @@ | |||
173 | #define ERRusestd 251 /* temporarily unable to use either raw | 173 | #define ERRusestd 251 /* temporarily unable to use either raw |
174 | or mpx */ | 174 | or mpx */ |
175 | #define ERR_NOTIFY_ENUM_DIR 1024 | 175 | #define ERR_NOTIFY_ENUM_DIR 1024 |
176 | #define ERRnoSuchUser 2238 /* user account does not exist */ | ||
176 | #define ERRaccountexpired 2239 | 177 | #define ERRaccountexpired 2239 |
177 | #define ERRbadclient 2240 | 178 | #define ERRbadclient 2240 /* can not logon from this client */ |
178 | #define ERRbadLogonTime 2241 | 179 | #define ERRbadLogonTime 2241 /* logon hours do not allow this */ |
179 | #define ERRpasswordExpired 2242 | 180 | #define ERRpasswordExpired 2242 |
180 | #define ERRnetlogonNotStarted 2455 | 181 | #define ERRnetlogonNotStarted 2455 |
181 | #define ERRnosupport 0xFFFF | 182 | #define ERRnosupport 0xFFFF |
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index 746bc9405db1..50b623ad9320 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c | |||
@@ -55,7 +55,7 @@ AllocMidQEntry(const struct smb_hdr *smb_buffer, struct cifsSesInfo *ses) | |||
55 | if (temp == NULL) | 55 | if (temp == NULL) |
56 | return temp; | 56 | return temp; |
57 | else { | 57 | else { |
58 | memset(temp, 0, sizeof (struct mid_q_entry)); | 58 | memset(temp, 0, sizeof(struct mid_q_entry)); |
59 | temp->mid = smb_buffer->Mid; /* always LE */ | 59 | temp->mid = smb_buffer->Mid; /* always LE */ |
60 | temp->pid = current->pid; | 60 | temp->pid = current->pid; |
61 | temp->command = smb_buffer->Command; | 61 | temp->command = smb_buffer->Command; |
@@ -158,7 +158,7 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer, | |||
158 | iov.iov_len = len; | 158 | iov.iov_len = len; |
159 | 159 | ||
160 | smb_msg.msg_name = sin; | 160 | smb_msg.msg_name = sin; |
161 | smb_msg.msg_namelen = sizeof (struct sockaddr); | 161 | smb_msg.msg_namelen = sizeof(struct sockaddr); |
162 | smb_msg.msg_control = NULL; | 162 | smb_msg.msg_control = NULL; |
163 | smb_msg.msg_controllen = 0; | 163 | smb_msg.msg_controllen = 0; |
164 | smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; /* BB add more flags?*/ | 164 | smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; /* BB add more flags?*/ |
@@ -228,7 +228,7 @@ smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec, | |||
228 | return -ENOTSOCK; /* BB eventually add reconnect code here */ | 228 | return -ENOTSOCK; /* BB eventually add reconnect code here */ |
229 | 229 | ||
230 | smb_msg.msg_name = sin; | 230 | smb_msg.msg_name = sin; |
231 | smb_msg.msg_namelen = sizeof (struct sockaddr); | 231 | smb_msg.msg_namelen = sizeof(struct sockaddr); |
232 | smb_msg.msg_control = NULL; | 232 | smb_msg.msg_control = NULL; |
233 | smb_msg.msg_controllen = 0; | 233 | smb_msg.msg_controllen = 0; |
234 | smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; /* BB add more flags?*/ | 234 | smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; /* BB add more flags?*/ |
@@ -308,7 +308,7 @@ smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec, | |||
308 | 308 | ||
309 | static int wait_for_free_request(struct cifsSesInfo *ses, const int long_op) | 309 | static int wait_for_free_request(struct cifsSesInfo *ses, const int long_op) |
310 | { | 310 | { |
311 | if (long_op == -1) { | 311 | if (long_op == CIFS_ASYNC_OP) { |
312 | /* oplock breaks must not be held up */ | 312 | /* oplock breaks must not be held up */ |
313 | atomic_inc(&ses->server->inFlight); | 313 | atomic_inc(&ses->server->inFlight); |
314 | } else { | 314 | } else { |
@@ -337,7 +337,7 @@ static int wait_for_free_request(struct cifsSesInfo *ses, const int long_op) | |||
337 | as they are allowed to block on server */ | 337 | as they are allowed to block on server */ |
338 | 338 | ||
339 | /* update # of requests on the wire to server */ | 339 | /* update # of requests on the wire to server */ |
340 | if (long_op < 3) | 340 | if (long_op != CIFS_BLOCKING_OP) |
341 | atomic_inc(&ses->server->inFlight); | 341 | atomic_inc(&ses->server->inFlight); |
342 | spin_unlock(&GlobalMid_Lock); | 342 | spin_unlock(&GlobalMid_Lock); |
343 | break; | 343 | break; |
@@ -363,9 +363,8 @@ static int allocate_mid(struct cifsSesInfo *ses, struct smb_hdr *in_buf, | |||
363 | } /* else ok - we are setting up session */ | 363 | } /* else ok - we are setting up session */ |
364 | } | 364 | } |
365 | *ppmidQ = AllocMidQEntry(in_buf, ses); | 365 | *ppmidQ = AllocMidQEntry(in_buf, ses); |
366 | if (*ppmidQ == NULL) { | 366 | if (*ppmidQ == NULL) |
367 | return -ENOMEM; | 367 | return -ENOMEM; |
368 | } | ||
369 | return 0; | 368 | return 0; |
370 | } | 369 | } |
371 | 370 | ||
@@ -416,17 +415,48 @@ static int wait_for_response(struct cifsSesInfo *ses, | |||
416 | } | 415 | } |
417 | } | 416 | } |
418 | 417 | ||
418 | |||
419 | /* | ||
420 | * | ||
421 | * Send an SMB Request. No response info (other than return code) | ||
422 | * needs to be parsed. | ||
423 | * | ||
424 | * flags indicate the type of request buffer and how long to wait | ||
425 | * and whether to log NT STATUS code (error) before mapping it to POSIX error | ||
426 | * | ||
427 | */ | ||
428 | int | ||
429 | SendReceiveNoRsp(const unsigned int xid, struct cifsSesInfo *ses, | ||
430 | struct smb_hdr *in_buf, int flags) | ||
431 | { | ||
432 | int rc; | ||
433 | struct kvec iov[1]; | ||
434 | int resp_buf_type; | ||
435 | |||
436 | iov[0].iov_base = (char *)in_buf; | ||
437 | iov[0].iov_len = in_buf->smb_buf_length + 4; | ||
438 | flags |= CIFS_NO_RESP; | ||
439 | rc = SendReceive2(xid, ses, iov, 1, &resp_buf_type, flags); | ||
440 | #ifdef CONFIG_CIFS_DEBUG2 | ||
441 | cFYI(1, ("SendRcvNoR flags %d rc %d", flags, rc)); | ||
442 | #endif | ||
443 | return rc; | ||
444 | } | ||
445 | |||
419 | int | 446 | int |
420 | SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, | 447 | SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, |
421 | struct kvec *iov, int n_vec, int *pRespBufType /* ret */, | 448 | struct kvec *iov, int n_vec, int *pRespBufType /* ret */, |
422 | const int long_op) | 449 | const int flags) |
423 | { | 450 | { |
424 | int rc = 0; | 451 | int rc = 0; |
452 | int long_op; | ||
425 | unsigned int receive_len; | 453 | unsigned int receive_len; |
426 | unsigned long timeout; | 454 | unsigned long timeout; |
427 | struct mid_q_entry *midQ; | 455 | struct mid_q_entry *midQ; |
428 | struct smb_hdr *in_buf = iov[0].iov_base; | 456 | struct smb_hdr *in_buf = iov[0].iov_base; |
429 | 457 | ||
458 | long_op = flags & CIFS_TIMEOUT_MASK; | ||
459 | |||
430 | *pRespBufType = CIFS_NO_BUFFER; /* no response buf yet */ | 460 | *pRespBufType = CIFS_NO_BUFFER; /* no response buf yet */ |
431 | 461 | ||
432 | if ((ses == NULL) || (ses->server == NULL)) { | 462 | if ((ses == NULL) || (ses->server == NULL)) { |
@@ -465,7 +495,6 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, | |||
465 | wake_up(&ses->server->request_q); | 495 | wake_up(&ses->server->request_q); |
466 | return rc; | 496 | return rc; |
467 | } | 497 | } |
468 | |||
469 | rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number); | 498 | rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number); |
470 | 499 | ||
471 | midQ->midState = MID_REQUEST_SUBMITTED; | 500 | midQ->midState = MID_REQUEST_SUBMITTED; |
@@ -485,15 +514,22 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, | |||
485 | if (rc < 0) | 514 | if (rc < 0) |
486 | goto out; | 515 | goto out; |
487 | 516 | ||
488 | if (long_op == -1) | 517 | if (long_op == CIFS_STD_OP) |
489 | goto out; | 518 | timeout = 15 * HZ; |
490 | else if (long_op == 2) /* writes past end of file can take loong time */ | 519 | else if (long_op == CIFS_VLONG_OP) /* e.g. slow writes past EOF */ |
491 | timeout = 180 * HZ; | 520 | timeout = 180 * HZ; |
492 | else if (long_op == 1) | 521 | else if (long_op == CIFS_LONG_OP) |
493 | timeout = 45 * HZ; /* should be greater than | 522 | timeout = 45 * HZ; /* should be greater than |
494 | servers oplock break timeout (about 43 seconds) */ | 523 | servers oplock break timeout (about 43 seconds) */ |
495 | else | 524 | else if (long_op == CIFS_ASYNC_OP) |
496 | timeout = 15 * HZ; | 525 | goto out; |
526 | else if (long_op == CIFS_BLOCKING_OP) | ||
527 | timeout = 0x7FFFFFFF; /* large, but not so large as to wrap */ | ||
528 | else { | ||
529 | cERROR(1, ("unknown timeout flag %d", long_op)); | ||
530 | rc = -EIO; | ||
531 | goto out; | ||
532 | } | ||
497 | 533 | ||
498 | /* wait for 15 seconds or until woken up due to response arriving or | 534 | /* wait for 15 seconds or until woken up due to response arriving or |
499 | due to last connection to this server being unmounted */ | 535 | due to last connection to this server being unmounted */ |
@@ -568,18 +604,19 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, | |||
568 | } | 604 | } |
569 | 605 | ||
570 | /* BB special case reconnect tid and uid here? */ | 606 | /* BB special case reconnect tid and uid here? */ |
571 | /* BB special case Errbadpassword and pwdexpired here */ | 607 | rc = map_smb_to_linux_error(midQ->resp_buf, |
572 | rc = map_smb_to_linux_error(midQ->resp_buf); | 608 | flags & CIFS_LOG_ERROR); |
573 | 609 | ||
574 | /* convert ByteCount if necessary */ | 610 | /* convert ByteCount if necessary */ |
575 | if (receive_len >= | 611 | if (receive_len >= sizeof(struct smb_hdr) - 4 |
576 | sizeof (struct smb_hdr) - | 612 | /* do not count RFC1001 header */ + |
577 | 4 /* do not count RFC1001 header */ + | ||
578 | (2 * midQ->resp_buf->WordCount) + 2 /* bcc */ ) | 613 | (2 * midQ->resp_buf->WordCount) + 2 /* bcc */ ) |
579 | BCC(midQ->resp_buf) = | 614 | BCC(midQ->resp_buf) = |
580 | le16_to_cpu(BCC_LE(midQ->resp_buf)); | 615 | le16_to_cpu(BCC_LE(midQ->resp_buf)); |
581 | midQ->resp_buf = NULL; /* mark it so will not be freed | 616 | if ((flags & CIFS_NO_RESP) == 0) |
582 | by DeleteMidQEntry */ | 617 | midQ->resp_buf = NULL; /* mark it so buf will |
618 | not be freed by | ||
619 | DeleteMidQEntry */ | ||
583 | } else { | 620 | } else { |
584 | rc = -EIO; | 621 | rc = -EIO; |
585 | cFYI(1, ("Bad MID state?")); | 622 | cFYI(1, ("Bad MID state?")); |
@@ -667,17 +704,25 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, | |||
667 | if (rc < 0) | 704 | if (rc < 0) |
668 | goto out; | 705 | goto out; |
669 | 706 | ||
670 | if (long_op == -1) | 707 | if (long_op == CIFS_STD_OP) |
708 | timeout = 15 * HZ; | ||
709 | /* wait for 15 seconds or until woken up due to response arriving or | ||
710 | due to last connection to this server being unmounted */ | ||
711 | else if (long_op == CIFS_ASYNC_OP) | ||
671 | goto out; | 712 | goto out; |
672 | else if (long_op == 2) /* writes past end of file can take loong time */ | 713 | else if (long_op == CIFS_VLONG_OP) /* writes past EOF can be slow */ |
673 | timeout = 180 * HZ; | 714 | timeout = 180 * HZ; |
674 | else if (long_op == 1) | 715 | else if (long_op == CIFS_LONG_OP) |
675 | timeout = 45 * HZ; /* should be greater than | 716 | timeout = 45 * HZ; /* should be greater than |
676 | servers oplock break timeout (about 43 seconds) */ | 717 | servers oplock break timeout (about 43 seconds) */ |
677 | else | 718 | else if (long_op == CIFS_BLOCKING_OP) |
678 | timeout = 15 * HZ; | 719 | timeout = 0x7FFFFFFF; /* large but no so large as to wrap */ |
679 | /* wait for 15 seconds or until woken up due to response arriving or | 720 | else { |
680 | due to last connection to this server being unmounted */ | 721 | cERROR(1, ("unknown timeout flag %d", long_op)); |
722 | rc = -EIO; | ||
723 | goto out; | ||
724 | } | ||
725 | |||
681 | if (signal_pending(current)) { | 726 | if (signal_pending(current)) { |
682 | /* if signal pending do not hold up user for full smb timeout | 727 | /* if signal pending do not hold up user for full smb timeout |
683 | but we still give response a chance to complete */ | 728 | but we still give response a chance to complete */ |
@@ -749,12 +794,11 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, | |||
749 | *pbytes_returned = out_buf->smb_buf_length; | 794 | *pbytes_returned = out_buf->smb_buf_length; |
750 | 795 | ||
751 | /* BB special case reconnect tid and uid here? */ | 796 | /* BB special case reconnect tid and uid here? */ |
752 | rc = map_smb_to_linux_error(out_buf); | 797 | rc = map_smb_to_linux_error(out_buf, 0 /* no log */ ); |
753 | 798 | ||
754 | /* convert ByteCount if necessary */ | 799 | /* convert ByteCount if necessary */ |
755 | if (receive_len >= | 800 | if (receive_len >= sizeof(struct smb_hdr) - 4 |
756 | sizeof (struct smb_hdr) - | 801 | /* do not count RFC1001 header */ + |
757 | 4 /* do not count RFC1001 header */ + | ||
758 | (2 * out_buf->WordCount) + 2 /* bcc */ ) | 802 | (2 * out_buf->WordCount) + 2 /* bcc */ ) |
759 | BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf)); | 803 | BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf)); |
760 | } else { | 804 | } else { |
@@ -817,7 +861,7 @@ send_lock_cancel(const unsigned int xid, struct cifsTconInfo *tcon, | |||
817 | pSMB->hdr.Mid = GetNextMid(ses->server); | 861 | pSMB->hdr.Mid = GetNextMid(ses->server); |
818 | 862 | ||
819 | return SendReceive(xid, ses, in_buf, out_buf, | 863 | return SendReceive(xid, ses, in_buf, out_buf, |
820 | &bytes_returned, 0); | 864 | &bytes_returned, CIFS_STD_OP); |
821 | } | 865 | } |
822 | 866 | ||
823 | int | 867 | int |
@@ -849,7 +893,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon, | |||
849 | to the same server. We may make this configurable later or | 893 | to the same server. We may make this configurable later or |
850 | use ses->maxReq */ | 894 | use ses->maxReq */ |
851 | 895 | ||
852 | rc = wait_for_free_request(ses, 3); | 896 | rc = wait_for_free_request(ses, CIFS_BLOCKING_OP); |
853 | if (rc) | 897 | if (rc) |
854 | return rc; | 898 | return rc; |
855 | 899 | ||
@@ -993,12 +1037,11 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon, | |||
993 | *pbytes_returned = out_buf->smb_buf_length; | 1037 | *pbytes_returned = out_buf->smb_buf_length; |
994 | 1038 | ||
995 | /* BB special case reconnect tid and uid here? */ | 1039 | /* BB special case reconnect tid and uid here? */ |
996 | rc = map_smb_to_linux_error(out_buf); | 1040 | rc = map_smb_to_linux_error(out_buf, 0 /* no log */ ); |
997 | 1041 | ||
998 | /* convert ByteCount if necessary */ | 1042 | /* convert ByteCount if necessary */ |
999 | if (receive_len >= | 1043 | if (receive_len >= sizeof(struct smb_hdr) - 4 |
1000 | sizeof (struct smb_hdr) - | 1044 | /* do not count RFC1001 header */ + |
1001 | 4 /* do not count RFC1001 header */ + | ||
1002 | (2 * out_buf->WordCount) + 2 /* bcc */ ) | 1045 | (2 * out_buf->WordCount) + 2 /* bcc */ ) |
1003 | BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf)); | 1046 | BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf)); |
1004 | } else { | 1047 | } else { |
diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c index f61e433d281c..54e8ef96cb79 100644 --- a/fs/cifs/xattr.c +++ b/fs/cifs/xattr.c | |||
@@ -261,21 +261,27 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name, | |||
261 | cifs_sb->local_nls, | 261 | cifs_sb->local_nls, |
262 | cifs_sb->mnt_cifs_flags & | 262 | cifs_sb->mnt_cifs_flags & |
263 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 263 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
264 | /* else if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { | 264 | #ifdef CONFIG_CIFS_EXPERIMENTAL |
265 | else if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { | ||
265 | __u16 fid; | 266 | __u16 fid; |
266 | int oplock = FALSE; | 267 | int oplock = FALSE; |
267 | rc = CIFSSMBOpen(xid, pTcon, full_path, | 268 | struct cifs_ntsd *pacl = NULL; |
268 | FILE_OPEN, GENERIC_READ, 0, &fid, | 269 | __u32 buflen = 0; |
269 | &oplock, NULL, cifs_sb->local_nls, | 270 | if (experimEnabled) |
270 | cifs_sb->mnt_cifs_flags & | 271 | rc = CIFSSMBOpen(xid, pTcon, full_path, |
271 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 272 | FILE_OPEN, GENERIC_READ, 0, &fid, |
272 | if(rc == 0) { | 273 | &oplock, NULL, cifs_sb->local_nls, |
273 | rc = CIFSSMBGetCIFSACL(xid, pTcon, fid, | 274 | cifs_sb->mnt_cifs_flags & |
274 | ea_value, buf_size, | 275 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
275 | ACL_TYPE_ACCESS); | 276 | /* else rc is EOPNOTSUPP from above */ |
277 | |||
278 | if (rc == 0) { | ||
279 | rc = CIFSSMBGetCIFSACL(xid, pTcon, fid, &pacl, | ||
280 | &buflen); | ||
276 | CIFSSMBClose(xid, pTcon, fid); | 281 | CIFSSMBClose(xid, pTcon, fid); |
277 | } | 282 | } |
278 | } */ /* BB enable after fixing up return data */ | 283 | } |
284 | #endif /* EXPERIMENTAL */ | ||
279 | #else | 285 | #else |
280 | cFYI(1, ("query POSIX ACL not supported yet")); | 286 | cFYI(1, ("query POSIX ACL not supported yet")); |
281 | #endif /* CONFIG_CIFS_POSIX */ | 287 | #endif /* CONFIG_CIFS_POSIX */ |
diff --git a/fs/coda/upcall.c b/fs/coda/upcall.c index cdb4c07a7870..359e531094dd 100644 --- a/fs/coda/upcall.c +++ b/fs/coda/upcall.c | |||
@@ -51,7 +51,7 @@ static void *alloc_upcall(int opcode, int size) | |||
51 | 51 | ||
52 | inp->ih.opcode = opcode; | 52 | inp->ih.opcode = opcode; |
53 | inp->ih.pid = current->pid; | 53 | inp->ih.pid = current->pid; |
54 | inp->ih.pgid = process_group(current); | 54 | inp->ih.pgid = task_pgrp_nr(current); |
55 | #ifdef CONFIG_CODA_FS_OLD_API | 55 | #ifdef CONFIG_CODA_FS_OLD_API |
56 | memset(&inp->ih.cred, 0, sizeof(struct coda_cred)); | 56 | memset(&inp->ih.cred, 0, sizeof(struct coda_cred)); |
57 | inp->ih.cred.cr_fsuid = current->fsuid; | 57 | inp->ih.cred.cr_fsuid = current->fsuid; |
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index a4284ccac1f9..e8b7c3a98a54 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c | |||
@@ -322,7 +322,7 @@ static int dev_ifname32(unsigned int fd, unsigned int cmd, unsigned long arg) | |||
322 | int err; | 322 | int err; |
323 | 323 | ||
324 | uifr = compat_alloc_user_space(sizeof(struct ifreq)); | 324 | uifr = compat_alloc_user_space(sizeof(struct ifreq)); |
325 | if (copy_in_user(uifr, compat_ptr(arg), sizeof(struct ifreq32))); | 325 | if (copy_in_user(uifr, compat_ptr(arg), sizeof(struct ifreq32))) |
326 | return -EFAULT; | 326 | return -EFAULT; |
327 | 327 | ||
328 | err = sys_ioctl(fd, SIOCGIFNAME, (unsigned long)uifr); | 328 | err = sys_ioctl(fd, SIOCGIFNAME, (unsigned long)uifr); |
@@ -1954,6 +1954,12 @@ ULONG_IOCTL(TIOCSCTTY) | |||
1954 | COMPATIBLE_IOCTL(TIOCGPTN) | 1954 | COMPATIBLE_IOCTL(TIOCGPTN) |
1955 | COMPATIBLE_IOCTL(TIOCSPTLCK) | 1955 | COMPATIBLE_IOCTL(TIOCSPTLCK) |
1956 | COMPATIBLE_IOCTL(TIOCSERGETLSR) | 1956 | COMPATIBLE_IOCTL(TIOCSERGETLSR) |
1957 | #ifdef TCGETS2 | ||
1958 | COMPATIBLE_IOCTL(TCGETS2) | ||
1959 | COMPATIBLE_IOCTL(TCSETS2) | ||
1960 | COMPATIBLE_IOCTL(TCSETSW2) | ||
1961 | COMPATIBLE_IOCTL(TCSETSF2) | ||
1962 | #endif | ||
1957 | /* Little f */ | 1963 | /* Little f */ |
1958 | COMPATIBLE_IOCTL(FIOCLEX) | 1964 | COMPATIBLE_IOCTL(FIOCLEX) |
1959 | COMPATIBLE_IOCTL(FIONCLEX) | 1965 | COMPATIBLE_IOCTL(FIONCLEX) |
diff --git a/fs/dcache.c b/fs/dcache.c index 5489b2d98a00..d9ca1e5ceb92 100644 --- a/fs/dcache.c +++ b/fs/dcache.c | |||
@@ -38,7 +38,7 @@ int sysctl_vfs_cache_pressure __read_mostly = 100; | |||
38 | EXPORT_SYMBOL_GPL(sysctl_vfs_cache_pressure); | 38 | EXPORT_SYMBOL_GPL(sysctl_vfs_cache_pressure); |
39 | 39 | ||
40 | __cacheline_aligned_in_smp DEFINE_SPINLOCK(dcache_lock); | 40 | __cacheline_aligned_in_smp DEFINE_SPINLOCK(dcache_lock); |
41 | static __cacheline_aligned_in_smp DEFINE_SEQLOCK(rename_lock); | 41 | __cacheline_aligned_in_smp DEFINE_SEQLOCK(rename_lock); |
42 | 42 | ||
43 | EXPORT_SYMBOL(dcache_lock); | 43 | EXPORT_SYMBOL(dcache_lock); |
44 | 44 | ||
@@ -1479,6 +1479,8 @@ static void switch_names(struct dentry *dentry, struct dentry *target) | |||
1479 | * dentry:internal, target:external. Steal target's | 1479 | * dentry:internal, target:external. Steal target's |
1480 | * storage and make target internal. | 1480 | * storage and make target internal. |
1481 | */ | 1481 | */ |
1482 | memcpy(target->d_iname, dentry->d_name.name, | ||
1483 | dentry->d_name.len + 1); | ||
1482 | dentry->d_name.name = target->d_name.name; | 1484 | dentry->d_name.name = target->d_name.name; |
1483 | target->d_name.name = target->d_iname; | 1485 | target->d_name.name = target->d_iname; |
1484 | } | 1486 | } |
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c index 11be8a325e26..6a713b33992f 100644 --- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c | |||
@@ -413,7 +413,7 @@ struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry, | |||
413 | d_move(old_dentry, dentry); | 413 | d_move(old_dentry, dentry); |
414 | fsnotify_move(old_dir->d_inode, new_dir->d_inode, old_name, | 414 | fsnotify_move(old_dir->d_inode, new_dir->d_inode, old_name, |
415 | old_dentry->d_name.name, S_ISDIR(old_dentry->d_inode->i_mode), | 415 | old_dentry->d_name.name, S_ISDIR(old_dentry->d_inode->i_mode), |
416 | NULL, old_dentry->d_inode); | 416 | NULL, old_dentry); |
417 | fsnotify_oldname_free(old_name); | 417 | fsnotify_oldname_free(old_name); |
418 | unlock_rename(new_dir, old_dir); | 418 | unlock_rename(new_dir, old_dir); |
419 | dput(dentry); | 419 | dput(dentry); |
diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c index 58bf3f5cdbe2..e9923ca9c2d9 100644 --- a/fs/dlm/lowcomms.c +++ b/fs/dlm/lowcomms.c | |||
@@ -1062,7 +1062,7 @@ static int sctp_listen_for_all(void) | |||
1062 | subscribe.sctp_shutdown_event = 1; | 1062 | subscribe.sctp_shutdown_event = 1; |
1063 | subscribe.sctp_partial_delivery_event = 1; | 1063 | subscribe.sctp_partial_delivery_event = 1; |
1064 | 1064 | ||
1065 | result = kernel_setsockopt(sock, SOL_SOCKET, SO_RCVBUF, | 1065 | result = kernel_setsockopt(sock, SOL_SOCKET, SO_RCVBUFFORCE, |
1066 | (char *)&bufsize, sizeof(bufsize)); | 1066 | (char *)&bufsize, sizeof(bufsize)); |
1067 | if (result) | 1067 | if (result) |
1068 | log_print("Error increasing buffer space on socket %d", result); | 1068 | log_print("Error increasing buffer space on socket %d", result); |
@@ -1454,10 +1454,6 @@ int dlm_lowcomms_start(void) | |||
1454 | if (!con_cache) | 1454 | if (!con_cache) |
1455 | goto out; | 1455 | goto out; |
1456 | 1456 | ||
1457 | /* Set some sysctl minima */ | ||
1458 | if (sysctl_rmem_max < NEEDED_RMEM) | ||
1459 | sysctl_rmem_max = NEEDED_RMEM; | ||
1460 | |||
1461 | /* Start listening */ | 1457 | /* Start listening */ |
1462 | if (dlm_config.ci_protocol == 0) | 1458 | if (dlm_config.ci_protocol == 0) |
1463 | error = tcp_listen_for_all(); | 1459 | error = tcp_listen_for_all(); |
diff --git a/fs/dlm/user.c b/fs/dlm/user.c index 6438941ab1f8..4f741546f4bb 100644 --- a/fs/dlm/user.c +++ b/fs/dlm/user.c | |||
@@ -456,7 +456,7 @@ static int check_version(struct dlm_write_request *req) | |||
456 | printk(KERN_DEBUG "dlm: process %s (%d) version mismatch " | 456 | printk(KERN_DEBUG "dlm: process %s (%d) version mismatch " |
457 | "user (%d.%d.%d) kernel (%d.%d.%d)\n", | 457 | "user (%d.%d.%d) kernel (%d.%d.%d)\n", |
458 | current->comm, | 458 | current->comm, |
459 | current->pid, | 459 | task_pid_nr(current), |
460 | req->version[0], | 460 | req->version[0], |
461 | req->version[1], | 461 | req->version[1], |
462 | req->version[2], | 462 | req->version[2], |
diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c index 1ae90ef2c74d..bbed2fd40fdc 100644 --- a/fs/ecryptfs/crypto.c +++ b/fs/ecryptfs/crypto.c | |||
@@ -115,11 +115,29 @@ static int ecryptfs_calculate_md5(char *dst, | |||
115 | } | 115 | } |
116 | crypt_stat->hash_tfm = desc.tfm; | 116 | crypt_stat->hash_tfm = desc.tfm; |
117 | } | 117 | } |
118 | crypto_hash_init(&desc); | 118 | rc = crypto_hash_init(&desc); |
119 | crypto_hash_update(&desc, &sg, len); | 119 | if (rc) { |
120 | crypto_hash_final(&desc, dst); | 120 | printk(KERN_ERR |
121 | mutex_unlock(&crypt_stat->cs_hash_tfm_mutex); | 121 | "%s: Error initializing crypto hash; rc = [%d]\n", |
122 | __FUNCTION__, rc); | ||
123 | goto out; | ||
124 | } | ||
125 | rc = crypto_hash_update(&desc, &sg, len); | ||
126 | if (rc) { | ||
127 | printk(KERN_ERR | ||
128 | "%s: Error updating crypto hash; rc = [%d]\n", | ||
129 | __FUNCTION__, rc); | ||
130 | goto out; | ||
131 | } | ||
132 | rc = crypto_hash_final(&desc, dst); | ||
133 | if (rc) { | ||
134 | printk(KERN_ERR | ||
135 | "%s: Error finalizing crypto hash; rc = [%d]\n", | ||
136 | __FUNCTION__, rc); | ||
137 | goto out; | ||
138 | } | ||
122 | out: | 139 | out: |
140 | mutex_unlock(&crypt_stat->cs_hash_tfm_mutex); | ||
123 | return rc; | 141 | return rc; |
124 | } | 142 | } |
125 | 143 | ||
@@ -279,13 +297,13 @@ int virt_to_scatterlist(const void *addr, int size, struct scatterlist *sg, | |||
279 | int offset; | 297 | int offset; |
280 | int remainder_of_page; | 298 | int remainder_of_page; |
281 | 299 | ||
300 | sg_init_table(sg, sg_size); | ||
301 | |||
282 | while (size > 0 && i < sg_size) { | 302 | while (size > 0 && i < sg_size) { |
283 | pg = virt_to_page(addr); | 303 | pg = virt_to_page(addr); |
284 | offset = offset_in_page(addr); | 304 | offset = offset_in_page(addr); |
285 | if (sg) { | 305 | if (sg) |
286 | sg[i].page = pg; | 306 | sg_set_page(&sg[i], pg, 0, offset); |
287 | sg[i].offset = offset; | ||
288 | } | ||
289 | remainder_of_page = PAGE_CACHE_SIZE - offset; | 307 | remainder_of_page = PAGE_CACHE_SIZE - offset; |
290 | if (size >= remainder_of_page) { | 308 | if (size >= remainder_of_page) { |
291 | if (sg) | 309 | if (sg) |
@@ -504,7 +522,6 @@ int ecryptfs_encrypt_page(struct page *page) | |||
504 | "\n", rc); | 522 | "\n", rc); |
505 | goto out; | 523 | goto out; |
506 | } | 524 | } |
507 | extent_offset++; | ||
508 | } | 525 | } |
509 | out: | 526 | out: |
510 | kfree(enc_extent_virt); | 527 | kfree(enc_extent_virt); |
@@ -640,7 +657,6 @@ int ecryptfs_decrypt_page(struct page *page) | |||
640 | "rc = [%d]\n", __FUNCTION__, rc); | 657 | "rc = [%d]\n", __FUNCTION__, rc); |
641 | goto out; | 658 | goto out; |
642 | } | 659 | } |
643 | extent_offset++; | ||
644 | } | 660 | } |
645 | out: | 661 | out: |
646 | kfree(enc_extent_virt); | 662 | kfree(enc_extent_virt); |
@@ -713,12 +729,11 @@ ecryptfs_encrypt_page_offset(struct ecryptfs_crypt_stat *crypt_stat, | |||
713 | { | 729 | { |
714 | struct scatterlist src_sg, dst_sg; | 730 | struct scatterlist src_sg, dst_sg; |
715 | 731 | ||
716 | src_sg.page = src_page; | 732 | sg_init_table(&src_sg, 1); |
717 | src_sg.offset = src_offset; | 733 | sg_init_table(&dst_sg, 1); |
718 | src_sg.length = size; | 734 | |
719 | dst_sg.page = dst_page; | 735 | sg_set_page(&src_sg, src_page, size, src_offset); |
720 | dst_sg.offset = dst_offset; | 736 | sg_set_page(&dst_sg, dst_page, size, dst_offset); |
721 | dst_sg.length = size; | ||
722 | return encrypt_scatterlist(crypt_stat, &dst_sg, &src_sg, size, iv); | 737 | return encrypt_scatterlist(crypt_stat, &dst_sg, &src_sg, size, iv); |
723 | } | 738 | } |
724 | 739 | ||
@@ -742,12 +757,12 @@ ecryptfs_decrypt_page_offset(struct ecryptfs_crypt_stat *crypt_stat, | |||
742 | { | 757 | { |
743 | struct scatterlist src_sg, dst_sg; | 758 | struct scatterlist src_sg, dst_sg; |
744 | 759 | ||
745 | src_sg.page = src_page; | 760 | sg_init_table(&src_sg, 1); |
746 | src_sg.offset = src_offset; | 761 | sg_set_page(&src_sg, src_page, size, src_offset); |
747 | src_sg.length = size; | 762 | |
748 | dst_sg.page = dst_page; | 763 | sg_init_table(&dst_sg, 1); |
749 | dst_sg.offset = dst_offset; | 764 | sg_set_page(&dst_sg, dst_page, size, dst_offset); |
750 | dst_sg.length = size; | 765 | |
751 | return decrypt_scatterlist(crypt_stat, &dst_sg, &src_sg, size, iv); | 766 | return decrypt_scatterlist(crypt_stat, &dst_sg, &src_sg, size, iv); |
752 | } | 767 | } |
753 | 768 | ||
diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c index 89d9710dd63d..263fed88c0ca 100644 --- a/fs/ecryptfs/keystore.c +++ b/fs/ecryptfs/keystore.c | |||
@@ -1040,6 +1040,9 @@ decrypt_passphrase_encrypted_session_key(struct ecryptfs_auth_tok *auth_tok, | |||
1040 | }; | 1040 | }; |
1041 | int rc = 0; | 1041 | int rc = 0; |
1042 | 1042 | ||
1043 | sg_init_table(&dst_sg, 1); | ||
1044 | sg_init_table(&src_sg, 1); | ||
1045 | |||
1043 | if (unlikely(ecryptfs_verbosity > 0)) { | 1046 | if (unlikely(ecryptfs_verbosity > 0)) { |
1044 | ecryptfs_printk( | 1047 | ecryptfs_printk( |
1045 | KERN_DEBUG, "Session key encryption key (size [%d]):\n", | 1048 | KERN_DEBUG, "Session key encryption key (size [%d]):\n", |
diff --git a/fs/ecryptfs/read_write.c b/fs/ecryptfs/read_write.c index 2150edf9a58e..6b7474a4336a 100644 --- a/fs/ecryptfs/read_write.c +++ b/fs/ecryptfs/read_write.c | |||
@@ -87,7 +87,7 @@ int ecryptfs_write_lower_page_segment(struct inode *ecryptfs_inode, | |||
87 | loff_t offset; | 87 | loff_t offset; |
88 | int rc; | 88 | int rc; |
89 | 89 | ||
90 | offset = ((((off_t)page_for_lower->index) << PAGE_CACHE_SHIFT) | 90 | offset = ((((loff_t)page_for_lower->index) << PAGE_CACHE_SHIFT) |
91 | + offset_in_page); | 91 | + offset_in_page); |
92 | virt = kmap(page_for_lower); | 92 | virt = kmap(page_for_lower); |
93 | rc = ecryptfs_write_lower(ecryptfs_inode, virt, offset, size); | 93 | rc = ecryptfs_write_lower(ecryptfs_inode, virt, offset, size); |
diff --git a/fs/efs/namei.c b/fs/efs/namei.c index 5276b19423c1..f7f407075be1 100644 --- a/fs/efs/namei.c +++ b/fs/efs/namei.c | |||
@@ -10,6 +10,8 @@ | |||
10 | #include <linux/string.h> | 10 | #include <linux/string.h> |
11 | #include <linux/efs_fs.h> | 11 | #include <linux/efs_fs.h> |
12 | #include <linux/smp_lock.h> | 12 | #include <linux/smp_lock.h> |
13 | #include <linux/exportfs.h> | ||
14 | |||
13 | 15 | ||
14 | static efs_ino_t efs_find_entry(struct inode *inode, const char *name, int len) { | 16 | static efs_ino_t efs_find_entry(struct inode *inode, const char *name, int len) { |
15 | struct buffer_head *bh; | 17 | struct buffer_head *bh; |
@@ -75,13 +77,10 @@ struct dentry *efs_lookup(struct inode *dir, struct dentry *dentry, struct namei | |||
75 | return NULL; | 77 | return NULL; |
76 | } | 78 | } |
77 | 79 | ||
78 | struct dentry *efs_get_dentry(struct super_block *sb, void *vobjp) | 80 | static struct inode *efs_nfs_get_inode(struct super_block *sb, u64 ino, |
81 | u32 generation) | ||
79 | { | 82 | { |
80 | __u32 *objp = vobjp; | ||
81 | unsigned long ino = objp[0]; | ||
82 | __u32 generation = objp[1]; | ||
83 | struct inode *inode; | 83 | struct inode *inode; |
84 | struct dentry *result; | ||
85 | 84 | ||
86 | if (ino == 0) | 85 | if (ino == 0) |
87 | return ERR_PTR(-ESTALE); | 86 | return ERR_PTR(-ESTALE); |
@@ -91,20 +90,25 @@ struct dentry *efs_get_dentry(struct super_block *sb, void *vobjp) | |||
91 | 90 | ||
92 | if (is_bad_inode(inode) || | 91 | if (is_bad_inode(inode) || |
93 | (generation && inode->i_generation != generation)) { | 92 | (generation && inode->i_generation != generation)) { |
94 | result = ERR_PTR(-ESTALE); | 93 | iput(inode); |
95 | goto out_iput; | 94 | return ERR_PTR(-ESTALE); |
96 | } | 95 | } |
97 | 96 | ||
98 | result = d_alloc_anon(inode); | 97 | return inode; |
99 | if (!result) { | 98 | } |
100 | result = ERR_PTR(-ENOMEM); | ||
101 | goto out_iput; | ||
102 | } | ||
103 | return result; | ||
104 | 99 | ||
105 | out_iput: | 100 | struct dentry *efs_fh_to_dentry(struct super_block *sb, struct fid *fid, |
106 | iput(inode); | 101 | int fh_len, int fh_type) |
107 | return result; | 102 | { |
103 | return generic_fh_to_dentry(sb, fid, fh_len, fh_type, | ||
104 | efs_nfs_get_inode); | ||
105 | } | ||
106 | |||
107 | struct dentry *efs_fh_to_parent(struct super_block *sb, struct fid *fid, | ||
108 | int fh_len, int fh_type) | ||
109 | { | ||
110 | return generic_fh_to_parent(sb, fid, fh_len, fh_type, | ||
111 | efs_nfs_get_inode); | ||
108 | } | 112 | } |
109 | 113 | ||
110 | struct dentry *efs_get_parent(struct dentry *child) | 114 | struct dentry *efs_get_parent(struct dentry *child) |
diff --git a/fs/efs/super.c b/fs/efs/super.c index 25d0326c5f1c..c79bc627f107 100644 --- a/fs/efs/super.c +++ b/fs/efs/super.c | |||
@@ -113,8 +113,9 @@ static const struct super_operations efs_superblock_operations = { | |||
113 | .remount_fs = efs_remount, | 113 | .remount_fs = efs_remount, |
114 | }; | 114 | }; |
115 | 115 | ||
116 | static struct export_operations efs_export_ops = { | 116 | static const struct export_operations efs_export_ops = { |
117 | .get_dentry = efs_get_dentry, | 117 | .fh_to_dentry = efs_fh_to_dentry, |
118 | .fh_to_parent = efs_fh_to_parent, | ||
118 | .get_parent = efs_get_parent, | 119 | .get_parent = efs_get_parent, |
119 | }; | 120 | }; |
120 | 121 | ||
diff --git a/fs/eventpoll.c b/fs/eventpoll.c index de6189291954..34f68f3a069a 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c | |||
@@ -325,15 +325,14 @@ static void ep_poll_safewake(struct poll_safewake *psw, wait_queue_head_t *wq) | |||
325 | int wake_nests = 0; | 325 | int wake_nests = 0; |
326 | unsigned long flags; | 326 | unsigned long flags; |
327 | struct task_struct *this_task = current; | 327 | struct task_struct *this_task = current; |
328 | struct list_head *lsthead = &psw->wake_task_list, *lnk; | 328 | struct list_head *lsthead = &psw->wake_task_list; |
329 | struct wake_task_node *tncur; | 329 | struct wake_task_node *tncur; |
330 | struct wake_task_node tnode; | 330 | struct wake_task_node tnode; |
331 | 331 | ||
332 | spin_lock_irqsave(&psw->lock, flags); | 332 | spin_lock_irqsave(&psw->lock, flags); |
333 | 333 | ||
334 | /* Try to see if the current task is already inside this wakeup call */ | 334 | /* Try to see if the current task is already inside this wakeup call */ |
335 | list_for_each(lnk, lsthead) { | 335 | list_for_each_entry(tncur, lsthead, llink) { |
336 | tncur = list_entry(lnk, struct wake_task_node, llink); | ||
337 | 336 | ||
338 | if (tncur->wq == wq || | 337 | if (tncur->wq == wq || |
339 | (tncur->task == this_task && ++wake_nests > EP_MAX_POLLWAKE_NESTS)) { | 338 | (tncur->task == this_task && ++wake_nests > EP_MAX_POLLWAKE_NESTS)) { |
@@ -234,7 +234,7 @@ static int __bprm_mm_init(struct linux_binprm *bprm) | |||
234 | vma->vm_start = vma->vm_end - PAGE_SIZE; | 234 | vma->vm_start = vma->vm_end - PAGE_SIZE; |
235 | 235 | ||
236 | vma->vm_flags = VM_STACK_FLAGS; | 236 | vma->vm_flags = VM_STACK_FLAGS; |
237 | vma->vm_page_prot = protection_map[vma->vm_flags & 0x7]; | 237 | vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); |
238 | err = insert_vm_struct(mm, vma); | 238 | err = insert_vm_struct(mm, vma); |
239 | if (err) { | 239 | if (err) { |
240 | up_write(&mm->mmap_sem); | 240 | up_write(&mm->mmap_sem); |
@@ -775,8 +775,8 @@ static int de_thread(struct task_struct *tsk) | |||
775 | * Reparenting needs write_lock on tasklist_lock, | 775 | * Reparenting needs write_lock on tasklist_lock, |
776 | * so it is safe to do it under read_lock. | 776 | * so it is safe to do it under read_lock. |
777 | */ | 777 | */ |
778 | if (unlikely(tsk->group_leader == child_reaper(tsk))) | 778 | if (unlikely(tsk->group_leader == task_child_reaper(tsk))) |
779 | tsk->nsproxy->pid_ns->child_reaper = tsk; | 779 | task_active_pid_ns(tsk)->child_reaper = tsk; |
780 | 780 | ||
781 | zap_other_threads(tsk); | 781 | zap_other_threads(tsk); |
782 | read_unlock(&tasklist_lock); | 782 | read_unlock(&tasklist_lock); |
@@ -841,8 +841,8 @@ static int de_thread(struct task_struct *tsk) | |||
841 | */ | 841 | */ |
842 | tsk->start_time = leader->start_time; | 842 | tsk->start_time = leader->start_time; |
843 | 843 | ||
844 | BUG_ON(leader->tgid != tsk->tgid); | 844 | BUG_ON(!same_thread_group(leader, tsk)); |
845 | BUG_ON(tsk->pid == tsk->tgid); | 845 | BUG_ON(has_group_leader_pid(tsk)); |
846 | /* | 846 | /* |
847 | * An exec() starts a new thread group with the | 847 | * An exec() starts a new thread group with the |
848 | * TGID of the previous thread group. Rehash the | 848 | * TGID of the previous thread group. Rehash the |
@@ -857,7 +857,7 @@ static int de_thread(struct task_struct *tsk) | |||
857 | */ | 857 | */ |
858 | detach_pid(tsk, PIDTYPE_PID); | 858 | detach_pid(tsk, PIDTYPE_PID); |
859 | tsk->pid = leader->pid; | 859 | tsk->pid = leader->pid; |
860 | attach_pid(tsk, PIDTYPE_PID, find_pid(tsk->pid)); | 860 | attach_pid(tsk, PIDTYPE_PID, task_pid(leader)); |
861 | transfer_pid(leader, tsk, PIDTYPE_PGID); | 861 | transfer_pid(leader, tsk, PIDTYPE_PGID); |
862 | transfer_pid(leader, tsk, PIDTYPE_SID); | 862 | transfer_pid(leader, tsk, PIDTYPE_SID); |
863 | list_replace_rcu(&leader->tasks, &tsk->tasks); | 863 | list_replace_rcu(&leader->tasks, &tsk->tasks); |
@@ -1433,7 +1433,7 @@ static int format_corename(char *corename, const char *pattern, long signr) | |||
1433 | case 'p': | 1433 | case 'p': |
1434 | pid_in_pattern = 1; | 1434 | pid_in_pattern = 1; |
1435 | rc = snprintf(out_ptr, out_end - out_ptr, | 1435 | rc = snprintf(out_ptr, out_end - out_ptr, |
1436 | "%d", current->tgid); | 1436 | "%d", task_tgid_vnr(current)); |
1437 | if (rc > out_end - out_ptr) | 1437 | if (rc > out_end - out_ptr) |
1438 | goto out; | 1438 | goto out; |
1439 | out_ptr += rc; | 1439 | out_ptr += rc; |
@@ -1513,7 +1513,7 @@ static int format_corename(char *corename, const char *pattern, long signr) | |||
1513 | if (!ispipe && !pid_in_pattern | 1513 | if (!ispipe && !pid_in_pattern |
1514 | && (core_uses_pid || atomic_read(¤t->mm->mm_users) != 1)) { | 1514 | && (core_uses_pid || atomic_read(¤t->mm->mm_users) != 1)) { |
1515 | rc = snprintf(out_ptr, out_end - out_ptr, | 1515 | rc = snprintf(out_ptr, out_end - out_ptr, |
1516 | ".%d", current->tgid); | 1516 | ".%d", task_tgid_vnr(current)); |
1517 | if (rc > out_end - out_ptr) | 1517 | if (rc > out_end - out_ptr) |
1518 | goto out; | 1518 | goto out; |
1519 | out_ptr += rc; | 1519 | out_ptr += rc; |
@@ -1692,7 +1692,10 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs) | |||
1692 | if (!binfmt || !binfmt->core_dump) | 1692 | if (!binfmt || !binfmt->core_dump) |
1693 | goto fail; | 1693 | goto fail; |
1694 | down_write(&mm->mmap_sem); | 1694 | down_write(&mm->mmap_sem); |
1695 | if (!get_dumpable(mm)) { | 1695 | /* |
1696 | * If another thread got here first, or we are not dumpable, bail out. | ||
1697 | */ | ||
1698 | if (mm->core_waiters || !get_dumpable(mm)) { | ||
1696 | up_write(&mm->mmap_sem); | 1699 | up_write(&mm->mmap_sem); |
1697 | goto fail; | 1700 | goto fail; |
1698 | } | 1701 | } |
@@ -1706,7 +1709,6 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs) | |||
1706 | flag = O_EXCL; /* Stop rewrite attacks */ | 1709 | flag = O_EXCL; /* Stop rewrite attacks */ |
1707 | current->fsuid = 0; /* Dump root private */ | 1710 | current->fsuid = 0; /* Dump root private */ |
1708 | } | 1711 | } |
1709 | set_dumpable(mm, 0); | ||
1710 | 1712 | ||
1711 | retval = coredump_wait(exit_code); | 1713 | retval = coredump_wait(exit_code); |
1712 | if (retval < 0) | 1714 | if (retval < 0) |
@@ -1778,6 +1780,12 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs) | |||
1778 | but keep the previous behaviour for now. */ | 1780 | but keep the previous behaviour for now. */ |
1779 | if (!ispipe && !S_ISREG(inode->i_mode)) | 1781 | if (!ispipe && !S_ISREG(inode->i_mode)) |
1780 | goto close_fail; | 1782 | goto close_fail; |
1783 | /* | ||
1784 | * Dont allow local users get cute and trick others to coredump | ||
1785 | * into their pre-created files: | ||
1786 | */ | ||
1787 | if (inode->i_uid != current->fsuid) | ||
1788 | goto close_fail; | ||
1781 | if (!file->f_op) | 1789 | if (!file->f_op) |
1782 | goto close_fail; | 1790 | goto close_fail; |
1783 | if (!file->f_op->write) | 1791 | if (!file->f_op->write) |
diff --git a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c index 8adb32a9387a..109ab5e44eca 100644 --- a/fs/exportfs/expfs.c +++ b/fs/exportfs/expfs.c | |||
@@ -1,4 +1,13 @@ | |||
1 | 1 | /* | |
2 | * Copyright (C) Neil Brown 2002 | ||
3 | * Copyright (C) Christoph Hellwig 2007 | ||
4 | * | ||
5 | * This file contains the code mapping from inodes to NFS file handles, | ||
6 | * and for mapping back from file handles to dentries. | ||
7 | * | ||
8 | * For details on why we do all the strange and hairy things in here | ||
9 | * take a look at Documentation/filesystems/Exporting. | ||
10 | */ | ||
2 | #include <linux/exportfs.h> | 11 | #include <linux/exportfs.h> |
3 | #include <linux/fs.h> | 12 | #include <linux/fs.h> |
4 | #include <linux/file.h> | 13 | #include <linux/file.h> |
@@ -9,32 +18,19 @@ | |||
9 | #define dprintk(fmt, args...) do{}while(0) | 18 | #define dprintk(fmt, args...) do{}while(0) |
10 | 19 | ||
11 | 20 | ||
12 | static int get_name(struct dentry *dentry, char *name, | 21 | static int get_name(struct vfsmount *mnt, struct dentry *dentry, char *name, |
13 | struct dentry *child); | 22 | struct dentry *child); |
14 | 23 | ||
15 | 24 | ||
16 | static struct dentry *exportfs_get_dentry(struct super_block *sb, void *obj) | 25 | static int exportfs_get_name(struct vfsmount *mnt, struct dentry *dir, |
26 | char *name, struct dentry *child) | ||
17 | { | 27 | { |
18 | struct dentry *result = ERR_PTR(-ESTALE); | 28 | const struct export_operations *nop = dir->d_sb->s_export_op; |
19 | |||
20 | if (sb->s_export_op->get_dentry) { | ||
21 | result = sb->s_export_op->get_dentry(sb, obj); | ||
22 | if (!result) | ||
23 | result = ERR_PTR(-ESTALE); | ||
24 | } | ||
25 | |||
26 | return result; | ||
27 | } | ||
28 | |||
29 | static int exportfs_get_name(struct dentry *dir, char *name, | ||
30 | struct dentry *child) | ||
31 | { | ||
32 | struct export_operations *nop = dir->d_sb->s_export_op; | ||
33 | 29 | ||
34 | if (nop->get_name) | 30 | if (nop->get_name) |
35 | return nop->get_name(dir, name, child); | 31 | return nop->get_name(dir, name, child); |
36 | else | 32 | else |
37 | return get_name(dir, name, child); | 33 | return get_name(mnt, dir, name, child); |
38 | } | 34 | } |
39 | 35 | ||
40 | /* | 36 | /* |
@@ -98,7 +94,7 @@ find_disconnected_root(struct dentry *dentry) | |||
98 | * It may already be, as the flag isn't always updated when connection happens. | 94 | * It may already be, as the flag isn't always updated when connection happens. |
99 | */ | 95 | */ |
100 | static int | 96 | static int |
101 | reconnect_path(struct super_block *sb, struct dentry *target_dir) | 97 | reconnect_path(struct vfsmount *mnt, struct dentry *target_dir) |
102 | { | 98 | { |
103 | char nbuf[NAME_MAX+1]; | 99 | char nbuf[NAME_MAX+1]; |
104 | int noprogress = 0; | 100 | int noprogress = 0; |
@@ -121,7 +117,7 @@ reconnect_path(struct super_block *sb, struct dentry *target_dir) | |||
121 | pd->d_flags &= ~DCACHE_DISCONNECTED; | 117 | pd->d_flags &= ~DCACHE_DISCONNECTED; |
122 | spin_unlock(&pd->d_lock); | 118 | spin_unlock(&pd->d_lock); |
123 | noprogress = 0; | 119 | noprogress = 0; |
124 | } else if (pd == sb->s_root) { | 120 | } else if (pd == mnt->mnt_sb->s_root) { |
125 | printk(KERN_ERR "export: Eeek filesystem root is not connected, impossible\n"); | 121 | printk(KERN_ERR "export: Eeek filesystem root is not connected, impossible\n"); |
126 | spin_lock(&pd->d_lock); | 122 | spin_lock(&pd->d_lock); |
127 | pd->d_flags &= ~DCACHE_DISCONNECTED; | 123 | pd->d_flags &= ~DCACHE_DISCONNECTED; |
@@ -147,8 +143,8 @@ reconnect_path(struct super_block *sb, struct dentry *target_dir) | |||
147 | struct dentry *npd; | 143 | struct dentry *npd; |
148 | 144 | ||
149 | mutex_lock(&pd->d_inode->i_mutex); | 145 | mutex_lock(&pd->d_inode->i_mutex); |
150 | if (sb->s_export_op->get_parent) | 146 | if (mnt->mnt_sb->s_export_op->get_parent) |
151 | ppd = sb->s_export_op->get_parent(pd); | 147 | ppd = mnt->mnt_sb->s_export_op->get_parent(pd); |
152 | mutex_unlock(&pd->d_inode->i_mutex); | 148 | mutex_unlock(&pd->d_inode->i_mutex); |
153 | 149 | ||
154 | if (IS_ERR(ppd)) { | 150 | if (IS_ERR(ppd)) { |
@@ -161,7 +157,7 @@ reconnect_path(struct super_block *sb, struct dentry *target_dir) | |||
161 | 157 | ||
162 | dprintk("%s: find name of %lu in %lu\n", __FUNCTION__, | 158 | dprintk("%s: find name of %lu in %lu\n", __FUNCTION__, |
163 | pd->d_inode->i_ino, ppd->d_inode->i_ino); | 159 | pd->d_inode->i_ino, ppd->d_inode->i_ino); |
164 | err = exportfs_get_name(ppd, nbuf, pd); | 160 | err = exportfs_get_name(mnt, ppd, nbuf, pd); |
165 | if (err) { | 161 | if (err) { |
166 | dput(ppd); | 162 | dput(ppd); |
167 | dput(pd); | 163 | dput(pd); |
@@ -214,125 +210,6 @@ reconnect_path(struct super_block *sb, struct dentry *target_dir) | |||
214 | return 0; | 210 | return 0; |
215 | } | 211 | } |
216 | 212 | ||
217 | /** | ||
218 | * find_exported_dentry - helper routine to implement export_operations->decode_fh | ||
219 | * @sb: The &super_block identifying the filesystem | ||
220 | * @obj: An opaque identifier of the object to be found - passed to | ||
221 | * get_inode | ||
222 | * @parent: An optional opqaue identifier of the parent of the object. | ||
223 | * @acceptable: A function used to test possible &dentries to see if they are | ||
224 | * acceptable | ||
225 | * @context: A parameter to @acceptable so that it knows on what basis to | ||
226 | * judge. | ||
227 | * | ||
228 | * find_exported_dentry is the central helper routine to enable file systems | ||
229 | * to provide the decode_fh() export_operation. It's main task is to take | ||
230 | * an &inode, find or create an appropriate &dentry structure, and possibly | ||
231 | * splice this into the dcache in the correct place. | ||
232 | * | ||
233 | * The decode_fh() operation provided by the filesystem should call | ||
234 | * find_exported_dentry() with the same parameters that it received except | ||
235 | * that instead of the file handle fragment, pointers to opaque identifiers | ||
236 | * for the object and optionally its parent are passed. The default decode_fh | ||
237 | * routine passes one pointer to the start of the filehandle fragment, and | ||
238 | * one 8 bytes into the fragment. It is expected that most filesystems will | ||
239 | * take this approach, though the offset to the parent identifier may well be | ||
240 | * different. | ||
241 | * | ||
242 | * find_exported_dentry() will call get_dentry to get an dentry pointer from | ||
243 | * the file system. If any &dentry in the d_alias list is acceptable, it will | ||
244 | * be returned. Otherwise find_exported_dentry() will attempt to splice a new | ||
245 | * &dentry into the dcache using get_name() and get_parent() to find the | ||
246 | * appropriate place. | ||
247 | */ | ||
248 | |||
249 | struct dentry * | ||
250 | find_exported_dentry(struct super_block *sb, void *obj, void *parent, | ||
251 | int (*acceptable)(void *context, struct dentry *de), | ||
252 | void *context) | ||
253 | { | ||
254 | struct dentry *result, *alias; | ||
255 | int err = -ESTALE; | ||
256 | |||
257 | /* | ||
258 | * Attempt to find the inode. | ||
259 | */ | ||
260 | result = exportfs_get_dentry(sb, obj); | ||
261 | if (IS_ERR(result)) | ||
262 | return result; | ||
263 | |||
264 | if (S_ISDIR(result->d_inode->i_mode)) { | ||
265 | if (!(result->d_flags & DCACHE_DISCONNECTED)) { | ||
266 | if (acceptable(context, result)) | ||
267 | return result; | ||
268 | err = -EACCES; | ||
269 | goto err_result; | ||
270 | } | ||
271 | |||
272 | err = reconnect_path(sb, result); | ||
273 | if (err) | ||
274 | goto err_result; | ||
275 | } else { | ||
276 | struct dentry *target_dir, *nresult; | ||
277 | char nbuf[NAME_MAX+1]; | ||
278 | |||
279 | alias = find_acceptable_alias(result, acceptable, context); | ||
280 | if (alias) | ||
281 | return alias; | ||
282 | |||
283 | if (parent == NULL) | ||
284 | goto err_result; | ||
285 | |||
286 | target_dir = exportfs_get_dentry(sb,parent); | ||
287 | if (IS_ERR(target_dir)) { | ||
288 | err = PTR_ERR(target_dir); | ||
289 | goto err_result; | ||
290 | } | ||
291 | |||
292 | err = reconnect_path(sb, target_dir); | ||
293 | if (err) { | ||
294 | dput(target_dir); | ||
295 | goto err_result; | ||
296 | } | ||
297 | |||
298 | /* | ||
299 | * As we weren't after a directory, have one more step to go. | ||
300 | */ | ||
301 | err = exportfs_get_name(target_dir, nbuf, result); | ||
302 | if (!err) { | ||
303 | mutex_lock(&target_dir->d_inode->i_mutex); | ||
304 | nresult = lookup_one_len(nbuf, target_dir, | ||
305 | strlen(nbuf)); | ||
306 | mutex_unlock(&target_dir->d_inode->i_mutex); | ||
307 | if (!IS_ERR(nresult)) { | ||
308 | if (nresult->d_inode) { | ||
309 | dput(result); | ||
310 | result = nresult; | ||
311 | } else | ||
312 | dput(nresult); | ||
313 | } | ||
314 | } | ||
315 | dput(target_dir); | ||
316 | } | ||
317 | |||
318 | alias = find_acceptable_alias(result, acceptable, context); | ||
319 | if (alias) | ||
320 | return alias; | ||
321 | |||
322 | /* drat - I just cannot find anything acceptable */ | ||
323 | dput(result); | ||
324 | /* It might be justifiable to return ESTALE here, | ||
325 | * but the filehandle at-least looks reasonable good | ||
326 | * and it may just be a permission problem, so returning | ||
327 | * -EACCESS is safer | ||
328 | */ | ||
329 | return ERR_PTR(-EACCES); | ||
330 | |||
331 | err_result: | ||
332 | dput(result); | ||
333 | return ERR_PTR(err); | ||
334 | } | ||
335 | |||
336 | struct getdents_callback { | 213 | struct getdents_callback { |
337 | char *name; /* name that was found. It already points to a | 214 | char *name; /* name that was found. It already points to a |
338 | buffer NAME_MAX+1 is size */ | 215 | buffer NAME_MAX+1 is size */ |
@@ -370,8 +247,8 @@ static int filldir_one(void * __buf, const char * name, int len, | |||
370 | * calls readdir on the parent until it finds an entry with | 247 | * calls readdir on the parent until it finds an entry with |
371 | * the same inode number as the child, and returns that. | 248 | * the same inode number as the child, and returns that. |
372 | */ | 249 | */ |
373 | static int get_name(struct dentry *dentry, char *name, | 250 | static int get_name(struct vfsmount *mnt, struct dentry *dentry, |
374 | struct dentry *child) | 251 | char *name, struct dentry *child) |
375 | { | 252 | { |
376 | struct inode *dir = dentry->d_inode; | 253 | struct inode *dir = dentry->d_inode; |
377 | int error; | 254 | int error; |
@@ -387,7 +264,7 @@ static int get_name(struct dentry *dentry, char *name, | |||
387 | /* | 264 | /* |
388 | * Open the directory ... | 265 | * Open the directory ... |
389 | */ | 266 | */ |
390 | file = dentry_open(dget(dentry), NULL, O_RDONLY); | 267 | file = dentry_open(dget(dentry), mntget(mnt), O_RDONLY); |
391 | error = PTR_ERR(file); | 268 | error = PTR_ERR(file); |
392 | if (IS_ERR(file)) | 269 | if (IS_ERR(file)) |
393 | goto out; | 270 | goto out; |
@@ -434,100 +311,177 @@ out: | |||
434 | * can be used to check that it is still valid. It places them in the | 311 | * can be used to check that it is still valid. It places them in the |
435 | * filehandle fragment where export_decode_fh expects to find them. | 312 | * filehandle fragment where export_decode_fh expects to find them. |
436 | */ | 313 | */ |
437 | static int export_encode_fh(struct dentry *dentry, __u32 *fh, int *max_len, | 314 | static int export_encode_fh(struct dentry *dentry, struct fid *fid, |
438 | int connectable) | 315 | int *max_len, int connectable) |
439 | { | 316 | { |
440 | struct inode * inode = dentry->d_inode; | 317 | struct inode * inode = dentry->d_inode; |
441 | int len = *max_len; | 318 | int len = *max_len; |
442 | int type = 1; | 319 | int type = FILEID_INO32_GEN; |
443 | 320 | ||
444 | if (len < 2 || (connectable && len < 4)) | 321 | if (len < 2 || (connectable && len < 4)) |
445 | return 255; | 322 | return 255; |
446 | 323 | ||
447 | len = 2; | 324 | len = 2; |
448 | fh[0] = inode->i_ino; | 325 | fid->i32.ino = inode->i_ino; |
449 | fh[1] = inode->i_generation; | 326 | fid->i32.gen = inode->i_generation; |
450 | if (connectable && !S_ISDIR(inode->i_mode)) { | 327 | if (connectable && !S_ISDIR(inode->i_mode)) { |
451 | struct inode *parent; | 328 | struct inode *parent; |
452 | 329 | ||
453 | spin_lock(&dentry->d_lock); | 330 | spin_lock(&dentry->d_lock); |
454 | parent = dentry->d_parent->d_inode; | 331 | parent = dentry->d_parent->d_inode; |
455 | fh[2] = parent->i_ino; | 332 | fid->i32.parent_ino = parent->i_ino; |
456 | fh[3] = parent->i_generation; | 333 | fid->i32.parent_gen = parent->i_generation; |
457 | spin_unlock(&dentry->d_lock); | 334 | spin_unlock(&dentry->d_lock); |
458 | len = 4; | 335 | len = 4; |
459 | type = 2; | 336 | type = FILEID_INO32_GEN_PARENT; |
460 | } | 337 | } |
461 | *max_len = len; | 338 | *max_len = len; |
462 | return type; | 339 | return type; |
463 | } | 340 | } |
464 | 341 | ||
465 | 342 | int exportfs_encode_fh(struct dentry *dentry, struct fid *fid, int *max_len, | |
466 | /** | ||
467 | * export_decode_fh - default export_operations->decode_fh function | ||
468 | * @sb: The superblock | ||
469 | * @fh: pointer to the file handle fragment | ||
470 | * @fh_len: length of file handle fragment | ||
471 | * @acceptable: function for testing acceptability of dentrys | ||
472 | * @context: context for @acceptable | ||
473 | * | ||
474 | * This is the default decode_fh() function. | ||
475 | * a fileid_type of 1 indicates that the filehandlefragment | ||
476 | * just contains an object identifier understood by get_dentry. | ||
477 | * a fileid_type of 2 says that there is also a directory | ||
478 | * identifier 8 bytes in to the filehandlefragement. | ||
479 | */ | ||
480 | static struct dentry *export_decode_fh(struct super_block *sb, __u32 *fh, int fh_len, | ||
481 | int fileid_type, | ||
482 | int (*acceptable)(void *context, struct dentry *de), | ||
483 | void *context) | ||
484 | { | ||
485 | __u32 parent[2]; | ||
486 | parent[0] = parent[1] = 0; | ||
487 | if (fh_len < 2 || fileid_type > 2) | ||
488 | return NULL; | ||
489 | if (fileid_type == 2) { | ||
490 | if (fh_len > 2) parent[0] = fh[2]; | ||
491 | if (fh_len > 3) parent[1] = fh[3]; | ||
492 | } | ||
493 | return find_exported_dentry(sb, fh, parent, | ||
494 | acceptable, context); | ||
495 | } | ||
496 | |||
497 | int exportfs_encode_fh(struct dentry *dentry, __u32 *fh, int *max_len, | ||
498 | int connectable) | 343 | int connectable) |
499 | { | 344 | { |
500 | struct export_operations *nop = dentry->d_sb->s_export_op; | 345 | const struct export_operations *nop = dentry->d_sb->s_export_op; |
501 | int error; | 346 | int error; |
502 | 347 | ||
503 | if (nop->encode_fh) | 348 | if (nop->encode_fh) |
504 | error = nop->encode_fh(dentry, fh, max_len, connectable); | 349 | error = nop->encode_fh(dentry, fid->raw, max_len, connectable); |
505 | else | 350 | else |
506 | error = export_encode_fh(dentry, fh, max_len, connectable); | 351 | error = export_encode_fh(dentry, fid, max_len, connectable); |
507 | 352 | ||
508 | return error; | 353 | return error; |
509 | } | 354 | } |
510 | EXPORT_SYMBOL_GPL(exportfs_encode_fh); | 355 | EXPORT_SYMBOL_GPL(exportfs_encode_fh); |
511 | 356 | ||
512 | struct dentry *exportfs_decode_fh(struct vfsmount *mnt, __u32 *fh, int fh_len, | 357 | struct dentry *exportfs_decode_fh(struct vfsmount *mnt, struct fid *fid, |
513 | int fileid_type, int (*acceptable)(void *, struct dentry *), | 358 | int fh_len, int fileid_type, |
514 | void *context) | 359 | int (*acceptable)(void *, struct dentry *), void *context) |
515 | { | 360 | { |
516 | struct export_operations *nop = mnt->mnt_sb->s_export_op; | 361 | const struct export_operations *nop = mnt->mnt_sb->s_export_op; |
517 | struct dentry *result; | 362 | struct dentry *result, *alias; |
363 | int err; | ||
518 | 364 | ||
519 | if (nop->decode_fh) { | 365 | /* |
520 | result = nop->decode_fh(mnt->mnt_sb, fh, fh_len, fileid_type, | 366 | * Try to get any dentry for the given file handle from the filesystem. |
521 | acceptable, context); | 367 | */ |
368 | result = nop->fh_to_dentry(mnt->mnt_sb, fid, fh_len, fileid_type); | ||
369 | if (!result) | ||
370 | result = ERR_PTR(-ESTALE); | ||
371 | if (IS_ERR(result)) | ||
372 | return result; | ||
373 | |||
374 | if (S_ISDIR(result->d_inode->i_mode)) { | ||
375 | /* | ||
376 | * This request is for a directory. | ||
377 | * | ||
378 | * On the positive side there is only one dentry for each | ||
379 | * directory inode. On the negative side this implies that we | ||
380 | * to ensure our dentry is connected all the way up to the | ||
381 | * filesystem root. | ||
382 | */ | ||
383 | if (result->d_flags & DCACHE_DISCONNECTED) { | ||
384 | err = reconnect_path(mnt, result); | ||
385 | if (err) | ||
386 | goto err_result; | ||
387 | } | ||
388 | |||
389 | if (!acceptable(context, result)) { | ||
390 | err = -EACCES; | ||
391 | goto err_result; | ||
392 | } | ||
393 | |||
394 | return result; | ||
522 | } else { | 395 | } else { |
523 | result = export_decode_fh(mnt->mnt_sb, fh, fh_len, fileid_type, | 396 | /* |
524 | acceptable, context); | 397 | * It's not a directory. Life is a little more complicated. |
398 | */ | ||
399 | struct dentry *target_dir, *nresult; | ||
400 | char nbuf[NAME_MAX+1]; | ||
401 | |||
402 | /* | ||
403 | * See if either the dentry we just got from the filesystem | ||
404 | * or any alias for it is acceptable. This is always true | ||
405 | * if this filesystem is exported without the subtreecheck | ||
406 | * option. If the filesystem is exported with the subtree | ||
407 | * check option there's a fair chance we need to look at | ||
408 | * the parent directory in the file handle and make sure | ||
409 | * it's connected to the filesystem root. | ||
410 | */ | ||
411 | alias = find_acceptable_alias(result, acceptable, context); | ||
412 | if (alias) | ||
413 | return alias; | ||
414 | |||
415 | /* | ||
416 | * Try to extract a dentry for the parent directory from the | ||
417 | * file handle. If this fails we'll have to give up. | ||
418 | */ | ||
419 | err = -ESTALE; | ||
420 | if (!nop->fh_to_parent) | ||
421 | goto err_result; | ||
422 | |||
423 | target_dir = nop->fh_to_parent(mnt->mnt_sb, fid, | ||
424 | fh_len, fileid_type); | ||
425 | if (!target_dir) | ||
426 | goto err_result; | ||
427 | err = PTR_ERR(target_dir); | ||
428 | if (IS_ERR(target_dir)) | ||
429 | goto err_result; | ||
430 | |||
431 | /* | ||
432 | * And as usual we need to make sure the parent directory is | ||
433 | * connected to the filesystem root. The VFS really doesn't | ||
434 | * like disconnected directories.. | ||
435 | */ | ||
436 | err = reconnect_path(mnt, target_dir); | ||
437 | if (err) { | ||
438 | dput(target_dir); | ||
439 | goto err_result; | ||
440 | } | ||
441 | |||
442 | /* | ||
443 | * Now that we've got both a well-connected parent and a | ||
444 | * dentry for the inode we're after, make sure that our | ||
445 | * inode is actually connected to the parent. | ||
446 | */ | ||
447 | err = exportfs_get_name(mnt, target_dir, nbuf, result); | ||
448 | if (!err) { | ||
449 | mutex_lock(&target_dir->d_inode->i_mutex); | ||
450 | nresult = lookup_one_len(nbuf, target_dir, | ||
451 | strlen(nbuf)); | ||
452 | mutex_unlock(&target_dir->d_inode->i_mutex); | ||
453 | if (!IS_ERR(nresult)) { | ||
454 | if (nresult->d_inode) { | ||
455 | dput(result); | ||
456 | result = nresult; | ||
457 | } else | ||
458 | dput(nresult); | ||
459 | } | ||
460 | } | ||
461 | |||
462 | /* | ||
463 | * At this point we are done with the parent, but it's pinned | ||
464 | * by the child dentry anyway. | ||
465 | */ | ||
466 | dput(target_dir); | ||
467 | |||
468 | /* | ||
469 | * And finally make sure the dentry is actually acceptable | ||
470 | * to NFSD. | ||
471 | */ | ||
472 | alias = find_acceptable_alias(result, acceptable, context); | ||
473 | if (!alias) { | ||
474 | err = -EACCES; | ||
475 | goto err_result; | ||
476 | } | ||
477 | |||
478 | return alias; | ||
525 | } | 479 | } |
526 | 480 | ||
527 | return result; | 481 | err_result: |
482 | dput(result); | ||
483 | return ERR_PTR(err); | ||
528 | } | 484 | } |
529 | EXPORT_SYMBOL_GPL(exportfs_decode_fh); | 485 | EXPORT_SYMBOL_GPL(exportfs_decode_fh); |
530 | 486 | ||
531 | EXPORT_SYMBOL(find_exported_dentry); | ||
532 | |||
533 | MODULE_LICENSE("GPL"); | 487 | MODULE_LICENSE("GPL"); |
diff --git a/fs/ext2/balloc.c b/fs/ext2/balloc.c index 18a42de25b55..377ad172d74b 100644 --- a/fs/ext2/balloc.c +++ b/fs/ext2/balloc.c | |||
@@ -69,14 +69,6 @@ struct ext2_group_desc * ext2_get_group_desc(struct super_block * sb, | |||
69 | return desc + offset; | 69 | return desc + offset; |
70 | } | 70 | } |
71 | 71 | ||
72 | static inline int | ||
73 | block_in_use(unsigned long block, struct super_block *sb, unsigned char *map) | ||
74 | { | ||
75 | return ext2_test_bit ((block - | ||
76 | le32_to_cpu(EXT2_SB(sb)->s_es->s_first_data_block)) % | ||
77 | EXT2_BLOCKS_PER_GROUP(sb), map); | ||
78 | } | ||
79 | |||
80 | /* | 72 | /* |
81 | * Read the bitmap for a given block_group, reading into the specified | 73 | * Read the bitmap for a given block_group, reading into the specified |
82 | * slot in the superblock's bitmap cache. | 74 | * slot in the superblock's bitmap cache. |
@@ -86,51 +78,20 @@ block_in_use(unsigned long block, struct super_block *sb, unsigned char *map) | |||
86 | static struct buffer_head * | 78 | static struct buffer_head * |
87 | read_block_bitmap(struct super_block *sb, unsigned int block_group) | 79 | read_block_bitmap(struct super_block *sb, unsigned int block_group) |
88 | { | 80 | { |
89 | int i; | ||
90 | struct ext2_group_desc * desc; | 81 | struct ext2_group_desc * desc; |
91 | struct buffer_head * bh = NULL; | 82 | struct buffer_head * bh = NULL; |
92 | unsigned int bitmap_blk; | 83 | |
93 | |||
94 | desc = ext2_get_group_desc (sb, block_group, NULL); | 84 | desc = ext2_get_group_desc (sb, block_group, NULL); |
95 | if (!desc) | 85 | if (!desc) |
96 | return NULL; | 86 | goto error_out; |
97 | bitmap_blk = le32_to_cpu(desc->bg_block_bitmap); | 87 | bh = sb_bread(sb, le32_to_cpu(desc->bg_block_bitmap)); |
98 | bh = sb_bread(sb, bitmap_blk); | ||
99 | if (!bh) | 88 | if (!bh) |
100 | ext2_error (sb, __FUNCTION__, | 89 | ext2_error (sb, "read_block_bitmap", |
101 | "Cannot read block bitmap - " | 90 | "Cannot read block bitmap - " |
102 | "block_group = %d, block_bitmap = %u", | 91 | "block_group = %d, block_bitmap = %u", |
103 | block_group, le32_to_cpu(desc->bg_block_bitmap)); | 92 | block_group, le32_to_cpu(desc->bg_block_bitmap)); |
104 | |||
105 | /* check whether block bitmap block number is set */ | ||
106 | if (!block_in_use(bitmap_blk, sb, bh->b_data)) { | ||
107 | /* bad block bitmap */ | ||
108 | goto error_out; | ||
109 | } | ||
110 | /* check whether the inode bitmap block number is set */ | ||
111 | bitmap_blk = le32_to_cpu(desc->bg_inode_bitmap); | ||
112 | if (!block_in_use(bitmap_blk, sb, bh->b_data)) { | ||
113 | /* bad block bitmap */ | ||
114 | goto error_out; | ||
115 | } | ||
116 | /* check whether the inode table block number is set */ | ||
117 | bitmap_blk = le32_to_cpu(desc->bg_inode_table); | ||
118 | for (i = 0; i < EXT2_SB(sb)->s_itb_per_group; i++, bitmap_blk++) { | ||
119 | if (!block_in_use(bitmap_blk, sb, bh->b_data)) { | ||
120 | /* bad block bitmap */ | ||
121 | goto error_out; | ||
122 | } | ||
123 | } | ||
124 | |||
125 | return bh; | ||
126 | |||
127 | error_out: | 93 | error_out: |
128 | brelse(bh); | 94 | return bh; |
129 | ext2_error(sb, __FUNCTION__, | ||
130 | "Invalid block bitmap - " | ||
131 | "block_group = %d, block = %u", | ||
132 | block_group, bitmap_blk); | ||
133 | return NULL; | ||
134 | } | 95 | } |
135 | 96 | ||
136 | static void release_blocks(struct super_block *sb, int count) | 97 | static void release_blocks(struct super_block *sb, int count) |
@@ -1461,7 +1422,6 @@ unsigned long ext2_count_free_blocks (struct super_block * sb) | |||
1461 | #endif | 1422 | #endif |
1462 | } | 1423 | } |
1463 | 1424 | ||
1464 | |||
1465 | static inline int test_root(int a, int b) | 1425 | static inline int test_root(int a, int b) |
1466 | { | 1426 | { |
1467 | int num = b; | 1427 | int num = b; |
diff --git a/fs/ext2/dir.c b/fs/ext2/dir.c index 05d9342bb64e..d868e26c15eb 100644 --- a/fs/ext2/dir.c +++ b/fs/ext2/dir.c | |||
@@ -28,6 +28,24 @@ | |||
28 | 28 | ||
29 | typedef struct ext2_dir_entry_2 ext2_dirent; | 29 | typedef struct ext2_dir_entry_2 ext2_dirent; |
30 | 30 | ||
31 | static inline unsigned ext2_rec_len_from_disk(__le16 dlen) | ||
32 | { | ||
33 | unsigned len = le16_to_cpu(dlen); | ||
34 | |||
35 | if (len == EXT2_MAX_REC_LEN) | ||
36 | return 1 << 16; | ||
37 | return len; | ||
38 | } | ||
39 | |||
40 | static inline __le16 ext2_rec_len_to_disk(unsigned len) | ||
41 | { | ||
42 | if (len == (1 << 16)) | ||
43 | return cpu_to_le16(EXT2_MAX_REC_LEN); | ||
44 | else if (len > (1 << 16)) | ||
45 | BUG(); | ||
46 | return cpu_to_le16(len); | ||
47 | } | ||
48 | |||
31 | /* | 49 | /* |
32 | * ext2 uses block-sized chunks. Arguably, sector-sized ones would be | 50 | * ext2 uses block-sized chunks. Arguably, sector-sized ones would be |
33 | * more robust, but we have what we have | 51 | * more robust, but we have what we have |
@@ -106,7 +124,7 @@ static void ext2_check_page(struct page *page) | |||
106 | } | 124 | } |
107 | for (offs = 0; offs <= limit - EXT2_DIR_REC_LEN(1); offs += rec_len) { | 125 | for (offs = 0; offs <= limit - EXT2_DIR_REC_LEN(1); offs += rec_len) { |
108 | p = (ext2_dirent *)(kaddr + offs); | 126 | p = (ext2_dirent *)(kaddr + offs); |
109 | rec_len = le16_to_cpu(p->rec_len); | 127 | rec_len = ext2_rec_len_from_disk(p->rec_len); |
110 | 128 | ||
111 | if (rec_len < EXT2_DIR_REC_LEN(1)) | 129 | if (rec_len < EXT2_DIR_REC_LEN(1)) |
112 | goto Eshort; | 130 | goto Eshort; |
@@ -204,7 +222,8 @@ static inline int ext2_match (int len, const char * const name, | |||
204 | */ | 222 | */ |
205 | static inline ext2_dirent *ext2_next_entry(ext2_dirent *p) | 223 | static inline ext2_dirent *ext2_next_entry(ext2_dirent *p) |
206 | { | 224 | { |
207 | return (ext2_dirent *)((char*)p + le16_to_cpu(p->rec_len)); | 225 | return (ext2_dirent *)((char *)p + |
226 | ext2_rec_len_from_disk(p->rec_len)); | ||
208 | } | 227 | } |
209 | 228 | ||
210 | static inline unsigned | 229 | static inline unsigned |
@@ -316,7 +335,7 @@ ext2_readdir (struct file * filp, void * dirent, filldir_t filldir) | |||
316 | return 0; | 335 | return 0; |
317 | } | 336 | } |
318 | } | 337 | } |
319 | filp->f_pos += le16_to_cpu(de->rec_len); | 338 | filp->f_pos += ext2_rec_len_from_disk(de->rec_len); |
320 | } | 339 | } |
321 | ext2_put_page(page); | 340 | ext2_put_page(page); |
322 | } | 341 | } |
@@ -425,7 +444,7 @@ void ext2_set_link(struct inode *dir, struct ext2_dir_entry_2 *de, | |||
425 | { | 444 | { |
426 | loff_t pos = page_offset(page) + | 445 | loff_t pos = page_offset(page) + |
427 | (char *) de - (char *) page_address(page); | 446 | (char *) de - (char *) page_address(page); |
428 | unsigned len = le16_to_cpu(de->rec_len); | 447 | unsigned len = ext2_rec_len_from_disk(de->rec_len); |
429 | int err; | 448 | int err; |
430 | 449 | ||
431 | lock_page(page); | 450 | lock_page(page); |
@@ -482,7 +501,7 @@ int ext2_add_link (struct dentry *dentry, struct inode *inode) | |||
482 | /* We hit i_size */ | 501 | /* We hit i_size */ |
483 | name_len = 0; | 502 | name_len = 0; |
484 | rec_len = chunk_size; | 503 | rec_len = chunk_size; |
485 | de->rec_len = cpu_to_le16(chunk_size); | 504 | de->rec_len = ext2_rec_len_to_disk(chunk_size); |
486 | de->inode = 0; | 505 | de->inode = 0; |
487 | goto got_it; | 506 | goto got_it; |
488 | } | 507 | } |
@@ -496,7 +515,7 @@ int ext2_add_link (struct dentry *dentry, struct inode *inode) | |||
496 | if (ext2_match (namelen, name, de)) | 515 | if (ext2_match (namelen, name, de)) |
497 | goto out_unlock; | 516 | goto out_unlock; |
498 | name_len = EXT2_DIR_REC_LEN(de->name_len); | 517 | name_len = EXT2_DIR_REC_LEN(de->name_len); |
499 | rec_len = le16_to_cpu(de->rec_len); | 518 | rec_len = ext2_rec_len_from_disk(de->rec_len); |
500 | if (!de->inode && rec_len >= reclen) | 519 | if (!de->inode && rec_len >= reclen) |
501 | goto got_it; | 520 | goto got_it; |
502 | if (rec_len >= name_len + reclen) | 521 | if (rec_len >= name_len + reclen) |
@@ -518,8 +537,8 @@ got_it: | |||
518 | goto out_unlock; | 537 | goto out_unlock; |
519 | if (de->inode) { | 538 | if (de->inode) { |
520 | ext2_dirent *de1 = (ext2_dirent *) ((char *) de + name_len); | 539 | ext2_dirent *de1 = (ext2_dirent *) ((char *) de + name_len); |
521 | de1->rec_len = cpu_to_le16(rec_len - name_len); | 540 | de1->rec_len = ext2_rec_len_to_disk(rec_len - name_len); |
522 | de->rec_len = cpu_to_le16(name_len); | 541 | de->rec_len = ext2_rec_len_to_disk(name_len); |
523 | de = de1; | 542 | de = de1; |
524 | } | 543 | } |
525 | de->name_len = namelen; | 544 | de->name_len = namelen; |
@@ -550,7 +569,8 @@ int ext2_delete_entry (struct ext2_dir_entry_2 * dir, struct page * page ) | |||
550 | struct inode *inode = mapping->host; | 569 | struct inode *inode = mapping->host; |
551 | char *kaddr = page_address(page); | 570 | char *kaddr = page_address(page); |
552 | unsigned from = ((char*)dir - kaddr) & ~(ext2_chunk_size(inode)-1); | 571 | unsigned from = ((char*)dir - kaddr) & ~(ext2_chunk_size(inode)-1); |
553 | unsigned to = ((char*)dir - kaddr) + le16_to_cpu(dir->rec_len); | 572 | unsigned to = ((char *)dir - kaddr) + |
573 | ext2_rec_len_from_disk(dir->rec_len); | ||
554 | loff_t pos; | 574 | loff_t pos; |
555 | ext2_dirent * pde = NULL; | 575 | ext2_dirent * pde = NULL; |
556 | ext2_dirent * de = (ext2_dirent *) (kaddr + from); | 576 | ext2_dirent * de = (ext2_dirent *) (kaddr + from); |
@@ -574,7 +594,7 @@ int ext2_delete_entry (struct ext2_dir_entry_2 * dir, struct page * page ) | |||
574 | &page, NULL); | 594 | &page, NULL); |
575 | BUG_ON(err); | 595 | BUG_ON(err); |
576 | if (pde) | 596 | if (pde) |
577 | pde->rec_len = cpu_to_le16(to - from); | 597 | pde->rec_len = ext2_rec_len_to_disk(to - from); |
578 | dir->inode = 0; | 598 | dir->inode = 0; |
579 | err = ext2_commit_chunk(page, pos, to - from); | 599 | err = ext2_commit_chunk(page, pos, to - from); |
580 | inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC; | 600 | inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC; |
@@ -610,14 +630,14 @@ int ext2_make_empty(struct inode *inode, struct inode *parent) | |||
610 | memset(kaddr, 0, chunk_size); | 630 | memset(kaddr, 0, chunk_size); |
611 | de = (struct ext2_dir_entry_2 *)kaddr; | 631 | de = (struct ext2_dir_entry_2 *)kaddr; |
612 | de->name_len = 1; | 632 | de->name_len = 1; |
613 | de->rec_len = cpu_to_le16(EXT2_DIR_REC_LEN(1)); | 633 | de->rec_len = ext2_rec_len_to_disk(EXT2_DIR_REC_LEN(1)); |
614 | memcpy (de->name, ".\0\0", 4); | 634 | memcpy (de->name, ".\0\0", 4); |
615 | de->inode = cpu_to_le32(inode->i_ino); | 635 | de->inode = cpu_to_le32(inode->i_ino); |
616 | ext2_set_de_type (de, inode); | 636 | ext2_set_de_type (de, inode); |
617 | 637 | ||
618 | de = (struct ext2_dir_entry_2 *)(kaddr + EXT2_DIR_REC_LEN(1)); | 638 | de = (struct ext2_dir_entry_2 *)(kaddr + EXT2_DIR_REC_LEN(1)); |
619 | de->name_len = 2; | 639 | de->name_len = 2; |
620 | de->rec_len = cpu_to_le16(chunk_size - EXT2_DIR_REC_LEN(1)); | 640 | de->rec_len = ext2_rec_len_to_disk(chunk_size - EXT2_DIR_REC_LEN(1)); |
621 | de->inode = cpu_to_le32(parent->i_ino); | 641 | de->inode = cpu_to_le32(parent->i_ino); |
622 | memcpy (de->name, "..\0", 4); | 642 | memcpy (de->name, "..\0", 4); |
623 | ext2_set_de_type (de, inode); | 643 | ext2_set_de_type (de, inode); |
diff --git a/fs/ext2/ext2.h b/fs/ext2/ext2.h index 7730388c4931..c87ae29c19cb 100644 --- a/fs/ext2/ext2.h +++ b/fs/ext2/ext2.h | |||
@@ -178,3 +178,10 @@ extern const struct inode_operations ext2_special_inode_operations; | |||
178 | /* symlink.c */ | 178 | /* symlink.c */ |
179 | extern const struct inode_operations ext2_fast_symlink_inode_operations; | 179 | extern const struct inode_operations ext2_fast_symlink_inode_operations; |
180 | extern const struct inode_operations ext2_symlink_inode_operations; | 180 | extern const struct inode_operations ext2_symlink_inode_operations; |
181 | |||
182 | static inline ext2_fsblk_t | ||
183 | ext2_group_first_block_no(struct super_block *sb, unsigned long group_no) | ||
184 | { | ||
185 | return group_no * (ext2_fsblk_t)EXT2_BLOCKS_PER_GROUP(sb) + | ||
186 | le32_to_cpu(EXT2_SB(sb)->s_es->s_first_data_block); | ||
187 | } | ||
diff --git a/fs/ext2/ioctl.c b/fs/ext2/ioctl.c index c2324d5fe4ac..320b2cb3d4d2 100644 --- a/fs/ext2/ioctl.c +++ b/fs/ext2/ioctl.c | |||
@@ -47,6 +47,11 @@ int ext2_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, | |||
47 | flags &= ~EXT2_DIRSYNC_FL; | 47 | flags &= ~EXT2_DIRSYNC_FL; |
48 | 48 | ||
49 | mutex_lock(&inode->i_mutex); | 49 | mutex_lock(&inode->i_mutex); |
50 | /* Is it quota file? Do not allow user to mess with it */ | ||
51 | if (IS_NOQUOTA(inode)) { | ||
52 | mutex_unlock(&inode->i_mutex); | ||
53 | return -EPERM; | ||
54 | } | ||
50 | oldflags = ei->i_flags; | 55 | oldflags = ei->i_flags; |
51 | 56 | ||
52 | /* | 57 | /* |
diff --git a/fs/ext2/super.c b/fs/ext2/super.c index 77bd5f9262f9..154e25f13d77 100644 --- a/fs/ext2/super.c +++ b/fs/ext2/super.c | |||
@@ -311,13 +311,10 @@ static const struct super_operations ext2_sops = { | |||
311 | #endif | 311 | #endif |
312 | }; | 312 | }; |
313 | 313 | ||
314 | static struct dentry *ext2_get_dentry(struct super_block *sb, void *vobjp) | 314 | static struct inode *ext2_nfs_get_inode(struct super_block *sb, |
315 | u64 ino, u32 generation) | ||
315 | { | 316 | { |
316 | __u32 *objp = vobjp; | ||
317 | unsigned long ino = objp[0]; | ||
318 | __u32 generation = objp[1]; | ||
319 | struct inode *inode; | 317 | struct inode *inode; |
320 | struct dentry *result; | ||
321 | 318 | ||
322 | if (ino < EXT2_FIRST_INO(sb) && ino != EXT2_ROOT_INO) | 319 | if (ino < EXT2_FIRST_INO(sb) && ino != EXT2_ROOT_INO) |
323 | return ERR_PTR(-ESTALE); | 320 | return ERR_PTR(-ESTALE); |
@@ -338,15 +335,21 @@ static struct dentry *ext2_get_dentry(struct super_block *sb, void *vobjp) | |||
338 | iput(inode); | 335 | iput(inode); |
339 | return ERR_PTR(-ESTALE); | 336 | return ERR_PTR(-ESTALE); |
340 | } | 337 | } |
341 | /* now to find a dentry. | 338 | return inode; |
342 | * If possible, get a well-connected one | 339 | } |
343 | */ | 340 | |
344 | result = d_alloc_anon(inode); | 341 | static struct dentry *ext2_fh_to_dentry(struct super_block *sb, struct fid *fid, |
345 | if (!result) { | 342 | int fh_len, int fh_type) |
346 | iput(inode); | 343 | { |
347 | return ERR_PTR(-ENOMEM); | 344 | return generic_fh_to_dentry(sb, fid, fh_len, fh_type, |
348 | } | 345 | ext2_nfs_get_inode); |
349 | return result; | 346 | } |
347 | |||
348 | static struct dentry *ext2_fh_to_parent(struct super_block *sb, struct fid *fid, | ||
349 | int fh_len, int fh_type) | ||
350 | { | ||
351 | return generic_fh_to_parent(sb, fid, fh_len, fh_type, | ||
352 | ext2_nfs_get_inode); | ||
350 | } | 353 | } |
351 | 354 | ||
352 | /* Yes, most of these are left as NULL!! | 355 | /* Yes, most of these are left as NULL!! |
@@ -354,9 +357,10 @@ static struct dentry *ext2_get_dentry(struct super_block *sb, void *vobjp) | |||
354 | * systems, but can be improved upon. | 357 | * systems, but can be improved upon. |
355 | * Currently only get_parent is required. | 358 | * Currently only get_parent is required. |
356 | */ | 359 | */ |
357 | static struct export_operations ext2_export_ops = { | 360 | static const struct export_operations ext2_export_ops = { |
361 | .fh_to_dentry = ext2_fh_to_dentry, | ||
362 | .fh_to_parent = ext2_fh_to_parent, | ||
358 | .get_parent = ext2_get_parent, | 363 | .get_parent = ext2_get_parent, |
359 | .get_dentry = ext2_get_dentry, | ||
360 | }; | 364 | }; |
361 | 365 | ||
362 | static unsigned long get_sb_block(void **data) | 366 | static unsigned long get_sb_block(void **data) |
diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c index 7a87d15523be..a8ba7e831278 100644 --- a/fs/ext3/balloc.c +++ b/fs/ext3/balloc.c | |||
@@ -80,14 +80,6 @@ struct ext3_group_desc * ext3_get_group_desc(struct super_block * sb, | |||
80 | return desc + offset; | 80 | return desc + offset; |
81 | } | 81 | } |
82 | 82 | ||
83 | static inline int | ||
84 | block_in_use(ext3_fsblk_t block, struct super_block *sb, unsigned char *map) | ||
85 | { | ||
86 | return ext3_test_bit ((block - | ||
87 | le32_to_cpu(EXT3_SB(sb)->s_es->s_first_data_block)) % | ||
88 | EXT3_BLOCKS_PER_GROUP(sb), map); | ||
89 | } | ||
90 | |||
91 | /** | 83 | /** |
92 | * read_block_bitmap() | 84 | * read_block_bitmap() |
93 | * @sb: super block | 85 | * @sb: super block |
@@ -101,51 +93,20 @@ block_in_use(ext3_fsblk_t block, struct super_block *sb, unsigned char *map) | |||
101 | static struct buffer_head * | 93 | static struct buffer_head * |
102 | read_block_bitmap(struct super_block *sb, unsigned int block_group) | 94 | read_block_bitmap(struct super_block *sb, unsigned int block_group) |
103 | { | 95 | { |
104 | int i; | ||
105 | struct ext3_group_desc * desc; | 96 | struct ext3_group_desc * desc; |
106 | struct buffer_head * bh = NULL; | 97 | struct buffer_head * bh = NULL; |
107 | ext3_fsblk_t bitmap_blk; | ||
108 | 98 | ||
109 | desc = ext3_get_group_desc (sb, block_group, NULL); | 99 | desc = ext3_get_group_desc (sb, block_group, NULL); |
110 | if (!desc) | 100 | if (!desc) |
111 | return NULL; | 101 | goto error_out; |
112 | bitmap_blk = le32_to_cpu(desc->bg_block_bitmap); | 102 | bh = sb_bread(sb, le32_to_cpu(desc->bg_block_bitmap)); |
113 | bh = sb_bread(sb, bitmap_blk); | ||
114 | if (!bh) | 103 | if (!bh) |
115 | ext3_error (sb, __FUNCTION__, | 104 | ext3_error (sb, "read_block_bitmap", |
116 | "Cannot read block bitmap - " | 105 | "Cannot read block bitmap - " |
117 | "block_group = %d, block_bitmap = %u", | 106 | "block_group = %d, block_bitmap = %u", |
118 | block_group, le32_to_cpu(desc->bg_block_bitmap)); | 107 | block_group, le32_to_cpu(desc->bg_block_bitmap)); |
119 | |||
120 | /* check whether block bitmap block number is set */ | ||
121 | if (!block_in_use(bitmap_blk, sb, bh->b_data)) { | ||
122 | /* bad block bitmap */ | ||
123 | goto error_out; | ||
124 | } | ||
125 | /* check whether the inode bitmap block number is set */ | ||
126 | bitmap_blk = le32_to_cpu(desc->bg_inode_bitmap); | ||
127 | if (!block_in_use(bitmap_blk, sb, bh->b_data)) { | ||
128 | /* bad block bitmap */ | ||
129 | goto error_out; | ||
130 | } | ||
131 | /* check whether the inode table block number is set */ | ||
132 | bitmap_blk = le32_to_cpu(desc->bg_inode_table); | ||
133 | for (i = 0; i < EXT3_SB(sb)->s_itb_per_group; i++, bitmap_blk++) { | ||
134 | if (!block_in_use(bitmap_blk, sb, bh->b_data)) { | ||
135 | /* bad block bitmap */ | ||
136 | goto error_out; | ||
137 | } | ||
138 | } | ||
139 | |||
140 | return bh; | ||
141 | |||
142 | error_out: | 108 | error_out: |
143 | brelse(bh); | 109 | return bh; |
144 | ext3_error(sb, __FUNCTION__, | ||
145 | "Invalid block bitmap - " | ||
146 | "block_group = %d, block = %lu", | ||
147 | block_group, bitmap_blk); | ||
148 | return NULL; | ||
149 | } | 110 | } |
150 | /* | 111 | /* |
151 | * The reservation window structure operations | 112 | * The reservation window structure operations |
@@ -1772,7 +1733,6 @@ ext3_fsblk_t ext3_count_free_blocks(struct super_block *sb) | |||
1772 | #endif | 1733 | #endif |
1773 | } | 1734 | } |
1774 | 1735 | ||
1775 | |||
1776 | static inline int test_root(int a, int b) | 1736 | static inline int test_root(int a, int b) |
1777 | { | 1737 | { |
1778 | int num = b; | 1738 | int num = b; |
diff --git a/fs/ext3/dir.c b/fs/ext3/dir.c index c8e4ee3af1d0..8ca3bfd72427 100644 --- a/fs/ext3/dir.c +++ b/fs/ext3/dir.c | |||
@@ -67,7 +67,7 @@ int ext3_check_dir_entry (const char * function, struct inode * dir, | |||
67 | unsigned long offset) | 67 | unsigned long offset) |
68 | { | 68 | { |
69 | const char * error_msg = NULL; | 69 | const char * error_msg = NULL; |
70 | const int rlen = le16_to_cpu(de->rec_len); | 70 | const int rlen = ext3_rec_len_from_disk(de->rec_len); |
71 | 71 | ||
72 | if (rlen < EXT3_DIR_REC_LEN(1)) | 72 | if (rlen < EXT3_DIR_REC_LEN(1)) |
73 | error_msg = "rec_len is smaller than minimal"; | 73 | error_msg = "rec_len is smaller than minimal"; |
@@ -173,10 +173,10 @@ revalidate: | |||
173 | * least that it is non-zero. A | 173 | * least that it is non-zero. A |
174 | * failure will be detected in the | 174 | * failure will be detected in the |
175 | * dirent test below. */ | 175 | * dirent test below. */ |
176 | if (le16_to_cpu(de->rec_len) < | 176 | if (ext3_rec_len_from_disk(de->rec_len) < |
177 | EXT3_DIR_REC_LEN(1)) | 177 | EXT3_DIR_REC_LEN(1)) |
178 | break; | 178 | break; |
179 | i += le16_to_cpu(de->rec_len); | 179 | i += ext3_rec_len_from_disk(de->rec_len); |
180 | } | 180 | } |
181 | offset = i; | 181 | offset = i; |
182 | filp->f_pos = (filp->f_pos & ~(sb->s_blocksize - 1)) | 182 | filp->f_pos = (filp->f_pos & ~(sb->s_blocksize - 1)) |
@@ -197,7 +197,7 @@ revalidate: | |||
197 | ret = stored; | 197 | ret = stored; |
198 | goto out; | 198 | goto out; |
199 | } | 199 | } |
200 | offset += le16_to_cpu(de->rec_len); | 200 | offset += ext3_rec_len_from_disk(de->rec_len); |
201 | if (le32_to_cpu(de->inode)) { | 201 | if (le32_to_cpu(de->inode)) { |
202 | /* We might block in the next section | 202 | /* We might block in the next section |
203 | * if the data destination is | 203 | * if the data destination is |
@@ -219,7 +219,7 @@ revalidate: | |||
219 | goto revalidate; | 219 | goto revalidate; |
220 | stored ++; | 220 | stored ++; |
221 | } | 221 | } |
222 | filp->f_pos += le16_to_cpu(de->rec_len); | 222 | filp->f_pos += ext3_rec_len_from_disk(de->rec_len); |
223 | } | 223 | } |
224 | offset = 0; | 224 | offset = 0; |
225 | brelse (bh); | 225 | brelse (bh); |
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index 3dec003b773e..9b162cd6c16c 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c | |||
@@ -2954,7 +2954,7 @@ int ext3_write_inode(struct inode *inode, int wait) | |||
2954 | return 0; | 2954 | return 0; |
2955 | 2955 | ||
2956 | if (ext3_journal_current_handle()) { | 2956 | if (ext3_journal_current_handle()) { |
2957 | jbd_debug(0, "called recursively, non-PF_MEMALLOC!\n"); | 2957 | jbd_debug(1, "called recursively, non-PF_MEMALLOC!\n"); |
2958 | dump_stack(); | 2958 | dump_stack(); |
2959 | return -EIO; | 2959 | return -EIO; |
2960 | } | 2960 | } |
diff --git a/fs/ext3/ioctl.c b/fs/ext3/ioctl.c index 4a2a02c95bf9..023a070f55f1 100644 --- a/fs/ext3/ioctl.c +++ b/fs/ext3/ioctl.c | |||
@@ -51,6 +51,11 @@ int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, | |||
51 | flags &= ~EXT3_DIRSYNC_FL; | 51 | flags &= ~EXT3_DIRSYNC_FL; |
52 | 52 | ||
53 | mutex_lock(&inode->i_mutex); | 53 | mutex_lock(&inode->i_mutex); |
54 | /* Is it quota file? Do not allow user to mess with it */ | ||
55 | if (IS_NOQUOTA(inode)) { | ||
56 | mutex_unlock(&inode->i_mutex); | ||
57 | return -EPERM; | ||
58 | } | ||
54 | oldflags = ei->i_flags; | 59 | oldflags = ei->i_flags; |
55 | 60 | ||
56 | /* The JOURNAL_DATA flag is modifiable only by root */ | 61 | /* The JOURNAL_DATA flag is modifiable only by root */ |
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c index ec8170adac53..4ab6f76e63d0 100644 --- a/fs/ext3/namei.c +++ b/fs/ext3/namei.c | |||
@@ -177,6 +177,16 @@ static int ext3_dx_add_entry(handle_t *handle, struct dentry *dentry, | |||
177 | struct inode *inode); | 177 | struct inode *inode); |
178 | 178 | ||
179 | /* | 179 | /* |
180 | * p is at least 6 bytes before the end of page | ||
181 | */ | ||
182 | static inline struct ext3_dir_entry_2 * | ||
183 | ext3_next_entry(struct ext3_dir_entry_2 *p) | ||
184 | { | ||
185 | return (struct ext3_dir_entry_2 *)((char *)p + | ||
186 | ext3_rec_len_from_disk(p->rec_len)); | ||
187 | } | ||
188 | |||
189 | /* | ||
180 | * Future: use high four bits of block for coalesce-on-delete flags | 190 | * Future: use high four bits of block for coalesce-on-delete flags |
181 | * Mask them off for now. | 191 | * Mask them off for now. |
182 | */ | 192 | */ |
@@ -280,7 +290,7 @@ static struct stats dx_show_leaf(struct dx_hash_info *hinfo, struct ext3_dir_ent | |||
280 | space += EXT3_DIR_REC_LEN(de->name_len); | 290 | space += EXT3_DIR_REC_LEN(de->name_len); |
281 | names++; | 291 | names++; |
282 | } | 292 | } |
283 | de = (struct ext3_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len)); | 293 | de = ext3_next_entry(de); |
284 | } | 294 | } |
285 | printk("(%i)\n", names); | 295 | printk("(%i)\n", names); |
286 | return (struct stats) { names, space, 1 }; | 296 | return (struct stats) { names, space, 1 }; |
@@ -547,14 +557,6 @@ static int ext3_htree_next_block(struct inode *dir, __u32 hash, | |||
547 | 557 | ||
548 | 558 | ||
549 | /* | 559 | /* |
550 | * p is at least 6 bytes before the end of page | ||
551 | */ | ||
552 | static inline struct ext3_dir_entry_2 *ext3_next_entry(struct ext3_dir_entry_2 *p) | ||
553 | { | ||
554 | return (struct ext3_dir_entry_2 *)((char*)p + le16_to_cpu(p->rec_len)); | ||
555 | } | ||
556 | |||
557 | /* | ||
558 | * This function fills a red-black tree with information from a | 560 | * This function fills a red-black tree with information from a |
559 | * directory block. It returns the number directory entries loaded | 561 | * directory block. It returns the number directory entries loaded |
560 | * into the tree. If there is an error it is returned in err. | 562 | * into the tree. If there is an error it is returned in err. |
@@ -720,7 +722,7 @@ static int dx_make_map (struct ext3_dir_entry_2 *de, int size, | |||
720 | cond_resched(); | 722 | cond_resched(); |
721 | } | 723 | } |
722 | /* XXX: do we need to check rec_len == 0 case? -Chris */ | 724 | /* XXX: do we need to check rec_len == 0 case? -Chris */ |
723 | de = (struct ext3_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len)); | 725 | de = ext3_next_entry(de); |
724 | } | 726 | } |
725 | return count; | 727 | return count; |
726 | } | 728 | } |
@@ -822,7 +824,7 @@ static inline int search_dirblock(struct buffer_head * bh, | |||
822 | return 1; | 824 | return 1; |
823 | } | 825 | } |
824 | /* prevent looping on a bad block */ | 826 | /* prevent looping on a bad block */ |
825 | de_len = le16_to_cpu(de->rec_len); | 827 | de_len = ext3_rec_len_from_disk(de->rec_len); |
826 | if (de_len <= 0) | 828 | if (de_len <= 0) |
827 | return -1; | 829 | return -1; |
828 | offset += de_len; | 830 | offset += de_len; |
@@ -1130,7 +1132,7 @@ dx_move_dirents(char *from, char *to, struct dx_map_entry *map, int count) | |||
1130 | rec_len = EXT3_DIR_REC_LEN(de->name_len); | 1132 | rec_len = EXT3_DIR_REC_LEN(de->name_len); |
1131 | memcpy (to, de, rec_len); | 1133 | memcpy (to, de, rec_len); |
1132 | ((struct ext3_dir_entry_2 *) to)->rec_len = | 1134 | ((struct ext3_dir_entry_2 *) to)->rec_len = |
1133 | cpu_to_le16(rec_len); | 1135 | ext3_rec_len_to_disk(rec_len); |
1134 | de->inode = 0; | 1136 | de->inode = 0; |
1135 | map++; | 1137 | map++; |
1136 | to += rec_len; | 1138 | to += rec_len; |
@@ -1149,13 +1151,12 @@ static struct ext3_dir_entry_2* dx_pack_dirents(char *base, int size) | |||
1149 | 1151 | ||
1150 | prev = to = de; | 1152 | prev = to = de; |
1151 | while ((char*)de < base + size) { | 1153 | while ((char*)de < base + size) { |
1152 | next = (struct ext3_dir_entry_2 *) ((char *) de + | 1154 | next = ext3_next_entry(de); |
1153 | le16_to_cpu(de->rec_len)); | ||
1154 | if (de->inode && de->name_len) { | 1155 | if (de->inode && de->name_len) { |
1155 | rec_len = EXT3_DIR_REC_LEN(de->name_len); | 1156 | rec_len = EXT3_DIR_REC_LEN(de->name_len); |
1156 | if (de > to) | 1157 | if (de > to) |
1157 | memmove(to, de, rec_len); | 1158 | memmove(to, de, rec_len); |
1158 | to->rec_len = cpu_to_le16(rec_len); | 1159 | to->rec_len = ext3_rec_len_to_disk(rec_len); |
1159 | prev = to; | 1160 | prev = to; |
1160 | to = (struct ext3_dir_entry_2 *) (((char *) to) + rec_len); | 1161 | to = (struct ext3_dir_entry_2 *) (((char *) to) + rec_len); |
1161 | } | 1162 | } |
@@ -1229,8 +1230,8 @@ static struct ext3_dir_entry_2 *do_split(handle_t *handle, struct inode *dir, | |||
1229 | /* Fancy dance to stay within two buffers */ | 1230 | /* Fancy dance to stay within two buffers */ |
1230 | de2 = dx_move_dirents(data1, data2, map + split, count - split); | 1231 | de2 = dx_move_dirents(data1, data2, map + split, count - split); |
1231 | de = dx_pack_dirents(data1,blocksize); | 1232 | de = dx_pack_dirents(data1,blocksize); |
1232 | de->rec_len = cpu_to_le16(data1 + blocksize - (char *) de); | 1233 | de->rec_len = ext3_rec_len_to_disk(data1 + blocksize - (char *) de); |
1233 | de2->rec_len = cpu_to_le16(data2 + blocksize - (char *) de2); | 1234 | de2->rec_len = ext3_rec_len_to_disk(data2 + blocksize - (char *) de2); |
1234 | dxtrace(dx_show_leaf (hinfo, (struct ext3_dir_entry_2 *) data1, blocksize, 1)); | 1235 | dxtrace(dx_show_leaf (hinfo, (struct ext3_dir_entry_2 *) data1, blocksize, 1)); |
1235 | dxtrace(dx_show_leaf (hinfo, (struct ext3_dir_entry_2 *) data2, blocksize, 1)); | 1236 | dxtrace(dx_show_leaf (hinfo, (struct ext3_dir_entry_2 *) data2, blocksize, 1)); |
1236 | 1237 | ||
@@ -1300,7 +1301,7 @@ static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry, | |||
1300 | return -EEXIST; | 1301 | return -EEXIST; |
1301 | } | 1302 | } |
1302 | nlen = EXT3_DIR_REC_LEN(de->name_len); | 1303 | nlen = EXT3_DIR_REC_LEN(de->name_len); |
1303 | rlen = le16_to_cpu(de->rec_len); | 1304 | rlen = ext3_rec_len_from_disk(de->rec_len); |
1304 | if ((de->inode? rlen - nlen: rlen) >= reclen) | 1305 | if ((de->inode? rlen - nlen: rlen) >= reclen) |
1305 | break; | 1306 | break; |
1306 | de = (struct ext3_dir_entry_2 *)((char *)de + rlen); | 1307 | de = (struct ext3_dir_entry_2 *)((char *)de + rlen); |
@@ -1319,11 +1320,11 @@ static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry, | |||
1319 | 1320 | ||
1320 | /* By now the buffer is marked for journaling */ | 1321 | /* By now the buffer is marked for journaling */ |
1321 | nlen = EXT3_DIR_REC_LEN(de->name_len); | 1322 | nlen = EXT3_DIR_REC_LEN(de->name_len); |
1322 | rlen = le16_to_cpu(de->rec_len); | 1323 | rlen = ext3_rec_len_from_disk(de->rec_len); |
1323 | if (de->inode) { | 1324 | if (de->inode) { |
1324 | struct ext3_dir_entry_2 *de1 = (struct ext3_dir_entry_2 *)((char *)de + nlen); | 1325 | struct ext3_dir_entry_2 *de1 = (struct ext3_dir_entry_2 *)((char *)de + nlen); |
1325 | de1->rec_len = cpu_to_le16(rlen - nlen); | 1326 | de1->rec_len = ext3_rec_len_to_disk(rlen - nlen); |
1326 | de->rec_len = cpu_to_le16(nlen); | 1327 | de->rec_len = ext3_rec_len_to_disk(nlen); |
1327 | de = de1; | 1328 | de = de1; |
1328 | } | 1329 | } |
1329 | de->file_type = EXT3_FT_UNKNOWN; | 1330 | de->file_type = EXT3_FT_UNKNOWN; |
@@ -1400,17 +1401,18 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry, | |||
1400 | 1401 | ||
1401 | /* The 0th block becomes the root, move the dirents out */ | 1402 | /* The 0th block becomes the root, move the dirents out */ |
1402 | fde = &root->dotdot; | 1403 | fde = &root->dotdot; |
1403 | de = (struct ext3_dir_entry_2 *)((char *)fde + le16_to_cpu(fde->rec_len)); | 1404 | de = (struct ext3_dir_entry_2 *)((char *)fde + |
1405 | ext3_rec_len_from_disk(fde->rec_len)); | ||
1404 | len = ((char *) root) + blocksize - (char *) de; | 1406 | len = ((char *) root) + blocksize - (char *) de; |
1405 | memcpy (data1, de, len); | 1407 | memcpy (data1, de, len); |
1406 | de = (struct ext3_dir_entry_2 *) data1; | 1408 | de = (struct ext3_dir_entry_2 *) data1; |
1407 | top = data1 + len; | 1409 | top = data1 + len; |
1408 | while ((char *)(de2=(void*)de+le16_to_cpu(de->rec_len)) < top) | 1410 | while ((char *)(de2 = ext3_next_entry(de)) < top) |
1409 | de = de2; | 1411 | de = de2; |
1410 | de->rec_len = cpu_to_le16(data1 + blocksize - (char *) de); | 1412 | de->rec_len = ext3_rec_len_to_disk(data1 + blocksize - (char *) de); |
1411 | /* Initialize the root; the dot dirents already exist */ | 1413 | /* Initialize the root; the dot dirents already exist */ |
1412 | de = (struct ext3_dir_entry_2 *) (&root->dotdot); | 1414 | de = (struct ext3_dir_entry_2 *) (&root->dotdot); |
1413 | de->rec_len = cpu_to_le16(blocksize - EXT3_DIR_REC_LEN(2)); | 1415 | de->rec_len = ext3_rec_len_to_disk(blocksize - EXT3_DIR_REC_LEN(2)); |
1414 | memset (&root->info, 0, sizeof(root->info)); | 1416 | memset (&root->info, 0, sizeof(root->info)); |
1415 | root->info.info_length = sizeof(root->info); | 1417 | root->info.info_length = sizeof(root->info); |
1416 | root->info.hash_version = EXT3_SB(dir->i_sb)->s_def_hash_version; | 1418 | root->info.hash_version = EXT3_SB(dir->i_sb)->s_def_hash_version; |
@@ -1490,7 +1492,7 @@ static int ext3_add_entry (handle_t *handle, struct dentry *dentry, | |||
1490 | return retval; | 1492 | return retval; |
1491 | de = (struct ext3_dir_entry_2 *) bh->b_data; | 1493 | de = (struct ext3_dir_entry_2 *) bh->b_data; |
1492 | de->inode = 0; | 1494 | de->inode = 0; |
1493 | de->rec_len = cpu_to_le16(blocksize); | 1495 | de->rec_len = ext3_rec_len_to_disk(blocksize); |
1494 | return add_dirent_to_buf(handle, dentry, inode, de, bh); | 1496 | return add_dirent_to_buf(handle, dentry, inode, de, bh); |
1495 | } | 1497 | } |
1496 | 1498 | ||
@@ -1553,7 +1555,7 @@ static int ext3_dx_add_entry(handle_t *handle, struct dentry *dentry, | |||
1553 | goto cleanup; | 1555 | goto cleanup; |
1554 | node2 = (struct dx_node *)(bh2->b_data); | 1556 | node2 = (struct dx_node *)(bh2->b_data); |
1555 | entries2 = node2->entries; | 1557 | entries2 = node2->entries; |
1556 | node2->fake.rec_len = cpu_to_le16(sb->s_blocksize); | 1558 | node2->fake.rec_len = ext3_rec_len_to_disk(sb->s_blocksize); |
1557 | node2->fake.inode = 0; | 1559 | node2->fake.inode = 0; |
1558 | BUFFER_TRACE(frame->bh, "get_write_access"); | 1560 | BUFFER_TRACE(frame->bh, "get_write_access"); |
1559 | err = ext3_journal_get_write_access(handle, frame->bh); | 1561 | err = ext3_journal_get_write_access(handle, frame->bh); |
@@ -1651,9 +1653,9 @@ static int ext3_delete_entry (handle_t *handle, | |||
1651 | BUFFER_TRACE(bh, "get_write_access"); | 1653 | BUFFER_TRACE(bh, "get_write_access"); |
1652 | ext3_journal_get_write_access(handle, bh); | 1654 | ext3_journal_get_write_access(handle, bh); |
1653 | if (pde) | 1655 | if (pde) |
1654 | pde->rec_len = | 1656 | pde->rec_len = ext3_rec_len_to_disk( |
1655 | cpu_to_le16(le16_to_cpu(pde->rec_len) + | 1657 | ext3_rec_len_from_disk(pde->rec_len) + |
1656 | le16_to_cpu(de->rec_len)); | 1658 | ext3_rec_len_from_disk(de->rec_len)); |
1657 | else | 1659 | else |
1658 | de->inode = 0; | 1660 | de->inode = 0; |
1659 | dir->i_version++; | 1661 | dir->i_version++; |
@@ -1661,10 +1663,9 @@ static int ext3_delete_entry (handle_t *handle, | |||
1661 | ext3_journal_dirty_metadata(handle, bh); | 1663 | ext3_journal_dirty_metadata(handle, bh); |
1662 | return 0; | 1664 | return 0; |
1663 | } | 1665 | } |
1664 | i += le16_to_cpu(de->rec_len); | 1666 | i += ext3_rec_len_from_disk(de->rec_len); |
1665 | pde = de; | 1667 | pde = de; |
1666 | de = (struct ext3_dir_entry_2 *) | 1668 | de = ext3_next_entry(de); |
1667 | ((char *) de + le16_to_cpu(de->rec_len)); | ||
1668 | } | 1669 | } |
1669 | return -ENOENT; | 1670 | return -ENOENT; |
1670 | } | 1671 | } |
@@ -1798,13 +1799,13 @@ retry: | |||
1798 | de = (struct ext3_dir_entry_2 *) dir_block->b_data; | 1799 | de = (struct ext3_dir_entry_2 *) dir_block->b_data; |
1799 | de->inode = cpu_to_le32(inode->i_ino); | 1800 | de->inode = cpu_to_le32(inode->i_ino); |
1800 | de->name_len = 1; | 1801 | de->name_len = 1; |
1801 | de->rec_len = cpu_to_le16(EXT3_DIR_REC_LEN(de->name_len)); | 1802 | de->rec_len = ext3_rec_len_to_disk(EXT3_DIR_REC_LEN(de->name_len)); |
1802 | strcpy (de->name, "."); | 1803 | strcpy (de->name, "."); |
1803 | ext3_set_de_type(dir->i_sb, de, S_IFDIR); | 1804 | ext3_set_de_type(dir->i_sb, de, S_IFDIR); |
1804 | de = (struct ext3_dir_entry_2 *) | 1805 | de = ext3_next_entry(de); |
1805 | ((char *) de + le16_to_cpu(de->rec_len)); | ||
1806 | de->inode = cpu_to_le32(dir->i_ino); | 1806 | de->inode = cpu_to_le32(dir->i_ino); |
1807 | de->rec_len = cpu_to_le16(inode->i_sb->s_blocksize-EXT3_DIR_REC_LEN(1)); | 1807 | de->rec_len = ext3_rec_len_to_disk(inode->i_sb->s_blocksize - |
1808 | EXT3_DIR_REC_LEN(1)); | ||
1808 | de->name_len = 2; | 1809 | de->name_len = 2; |
1809 | strcpy (de->name, ".."); | 1810 | strcpy (de->name, ".."); |
1810 | ext3_set_de_type(dir->i_sb, de, S_IFDIR); | 1811 | ext3_set_de_type(dir->i_sb, de, S_IFDIR); |
@@ -1856,8 +1857,7 @@ static int empty_dir (struct inode * inode) | |||
1856 | return 1; | 1857 | return 1; |
1857 | } | 1858 | } |
1858 | de = (struct ext3_dir_entry_2 *) bh->b_data; | 1859 | de = (struct ext3_dir_entry_2 *) bh->b_data; |
1859 | de1 = (struct ext3_dir_entry_2 *) | 1860 | de1 = ext3_next_entry(de); |
1860 | ((char *) de + le16_to_cpu(de->rec_len)); | ||
1861 | if (le32_to_cpu(de->inode) != inode->i_ino || | 1861 | if (le32_to_cpu(de->inode) != inode->i_ino || |
1862 | !le32_to_cpu(de1->inode) || | 1862 | !le32_to_cpu(de1->inode) || |
1863 | strcmp (".", de->name) || | 1863 | strcmp (".", de->name) || |
@@ -1868,9 +1868,9 @@ static int empty_dir (struct inode * inode) | |||
1868 | brelse (bh); | 1868 | brelse (bh); |
1869 | return 1; | 1869 | return 1; |
1870 | } | 1870 | } |
1871 | offset = le16_to_cpu(de->rec_len) + le16_to_cpu(de1->rec_len); | 1871 | offset = ext3_rec_len_from_disk(de->rec_len) + |
1872 | de = (struct ext3_dir_entry_2 *) | 1872 | ext3_rec_len_from_disk(de1->rec_len); |
1873 | ((char *) de1 + le16_to_cpu(de1->rec_len)); | 1873 | de = ext3_next_entry(de1); |
1874 | while (offset < inode->i_size ) { | 1874 | while (offset < inode->i_size ) { |
1875 | if (!bh || | 1875 | if (!bh || |
1876 | (void *) de >= (void *) (bh->b_data+sb->s_blocksize)) { | 1876 | (void *) de >= (void *) (bh->b_data+sb->s_blocksize)) { |
@@ -1899,9 +1899,8 @@ static int empty_dir (struct inode * inode) | |||
1899 | brelse (bh); | 1899 | brelse (bh); |
1900 | return 0; | 1900 | return 0; |
1901 | } | 1901 | } |
1902 | offset += le16_to_cpu(de->rec_len); | 1902 | offset += ext3_rec_len_from_disk(de->rec_len); |
1903 | de = (struct ext3_dir_entry_2 *) | 1903 | de = ext3_next_entry(de); |
1904 | ((char *) de + le16_to_cpu(de->rec_len)); | ||
1905 | } | 1904 | } |
1906 | brelse (bh); | 1905 | brelse (bh); |
1907 | return 1; | 1906 | return 1; |
@@ -2255,8 +2254,7 @@ retry: | |||
2255 | } | 2254 | } |
2256 | 2255 | ||
2257 | #define PARENT_INO(buffer) \ | 2256 | #define PARENT_INO(buffer) \ |
2258 | ((struct ext3_dir_entry_2 *) ((char *) buffer + \ | 2257 | (ext3_next_entry((struct ext3_dir_entry_2 *)(buffer))->inode) |
2259 | le16_to_cpu(((struct ext3_dir_entry_2 *) buffer)->rec_len)))->inode | ||
2260 | 2258 | ||
2261 | /* | 2259 | /* |
2262 | * Anybody can rename anything with this: the permission checks are left to the | 2260 | * Anybody can rename anything with this: the permission checks are left to the |
diff --git a/fs/ext3/super.c b/fs/ext3/super.c index 81868c0bc40e..de55da9e28ba 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c | |||
@@ -631,13 +631,10 @@ static int ext3_show_options(struct seq_file *seq, struct vfsmount *vfs) | |||
631 | } | 631 | } |
632 | 632 | ||
633 | 633 | ||
634 | static struct dentry *ext3_get_dentry(struct super_block *sb, void *vobjp) | 634 | static struct inode *ext3_nfs_get_inode(struct super_block *sb, |
635 | u64 ino, u32 generation) | ||
635 | { | 636 | { |
636 | __u32 *objp = vobjp; | ||
637 | unsigned long ino = objp[0]; | ||
638 | __u32 generation = objp[1]; | ||
639 | struct inode *inode; | 637 | struct inode *inode; |
640 | struct dentry *result; | ||
641 | 638 | ||
642 | if (ino < EXT3_FIRST_INO(sb) && ino != EXT3_ROOT_INO) | 639 | if (ino < EXT3_FIRST_INO(sb) && ino != EXT3_ROOT_INO) |
643 | return ERR_PTR(-ESTALE); | 640 | return ERR_PTR(-ESTALE); |
@@ -660,15 +657,22 @@ static struct dentry *ext3_get_dentry(struct super_block *sb, void *vobjp) | |||
660 | iput(inode); | 657 | iput(inode); |
661 | return ERR_PTR(-ESTALE); | 658 | return ERR_PTR(-ESTALE); |
662 | } | 659 | } |
663 | /* now to find a dentry. | 660 | |
664 | * If possible, get a well-connected one | 661 | return inode; |
665 | */ | 662 | } |
666 | result = d_alloc_anon(inode); | 663 | |
667 | if (!result) { | 664 | static struct dentry *ext3_fh_to_dentry(struct super_block *sb, struct fid *fid, |
668 | iput(inode); | 665 | int fh_len, int fh_type) |
669 | return ERR_PTR(-ENOMEM); | 666 | { |
670 | } | 667 | return generic_fh_to_dentry(sb, fid, fh_len, fh_type, |
671 | return result; | 668 | ext3_nfs_get_inode); |
669 | } | ||
670 | |||
671 | static struct dentry *ext3_fh_to_parent(struct super_block *sb, struct fid *fid, | ||
672 | int fh_len, int fh_type) | ||
673 | { | ||
674 | return generic_fh_to_parent(sb, fid, fh_len, fh_type, | ||
675 | ext3_nfs_get_inode); | ||
672 | } | 676 | } |
673 | 677 | ||
674 | #ifdef CONFIG_QUOTA | 678 | #ifdef CONFIG_QUOTA |
@@ -737,9 +741,10 @@ static const struct super_operations ext3_sops = { | |||
737 | #endif | 741 | #endif |
738 | }; | 742 | }; |
739 | 743 | ||
740 | static struct export_operations ext3_export_ops = { | 744 | static const struct export_operations ext3_export_ops = { |
745 | .fh_to_dentry = ext3_fh_to_dentry, | ||
746 | .fh_to_parent = ext3_fh_to_parent, | ||
741 | .get_parent = ext3_get_parent, | 747 | .get_parent = ext3_get_parent, |
742 | .get_dentry = ext3_get_dentry, | ||
743 | }; | 748 | }; |
744 | 749 | ||
745 | enum { | 750 | enum { |
diff --git a/fs/ext3/xattr.c b/fs/ext3/xattr.c index f58cbb26323e..408373819e34 100644 --- a/fs/ext3/xattr.c +++ b/fs/ext3/xattr.c | |||
@@ -741,12 +741,11 @@ ext3_xattr_block_set(handle_t *handle, struct inode *inode, | |||
741 | } | 741 | } |
742 | } else { | 742 | } else { |
743 | /* Allocate a buffer where we construct the new block. */ | 743 | /* Allocate a buffer where we construct the new block. */ |
744 | s->base = kmalloc(sb->s_blocksize, GFP_KERNEL); | 744 | s->base = kzalloc(sb->s_blocksize, GFP_KERNEL); |
745 | /* assert(header == s->base) */ | 745 | /* assert(header == s->base) */ |
746 | error = -ENOMEM; | 746 | error = -ENOMEM; |
747 | if (s->base == NULL) | 747 | if (s->base == NULL) |
748 | goto cleanup; | 748 | goto cleanup; |
749 | memset(s->base, 0, sb->s_blocksize); | ||
750 | header(s->base)->h_magic = cpu_to_le32(EXT3_XATTR_MAGIC); | 749 | header(s->base)->h_magic = cpu_to_le32(EXT3_XATTR_MAGIC); |
751 | header(s->base)->h_blocks = cpu_to_le32(1); | 750 | header(s->base)->h_blocks = cpu_to_le32(1); |
752 | header(s->base)->h_refcount = cpu_to_le32(1); | 751 | header(s->base)->h_refcount = cpu_to_le32(1); |
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c index e906b65448e2..71ee95e534fd 100644 --- a/fs/ext4/balloc.c +++ b/fs/ext4/balloc.c | |||
@@ -189,15 +189,6 @@ struct ext4_group_desc * ext4_get_group_desc(struct super_block * sb, | |||
189 | return desc; | 189 | return desc; |
190 | } | 190 | } |
191 | 191 | ||
192 | static inline int | ||
193 | block_in_use(ext4_fsblk_t block, struct super_block *sb, unsigned char *map) | ||
194 | { | ||
195 | ext4_grpblk_t offset; | ||
196 | |||
197 | ext4_get_group_no_and_offset(sb, block, NULL, &offset); | ||
198 | return ext4_test_bit (offset, map); | ||
199 | } | ||
200 | |||
201 | /** | 192 | /** |
202 | * read_block_bitmap() | 193 | * read_block_bitmap() |
203 | * @sb: super block | 194 | * @sb: super block |
@@ -211,7 +202,6 @@ block_in_use(ext4_fsblk_t block, struct super_block *sb, unsigned char *map) | |||
211 | struct buffer_head * | 202 | struct buffer_head * |
212 | read_block_bitmap(struct super_block *sb, unsigned int block_group) | 203 | read_block_bitmap(struct super_block *sb, unsigned int block_group) |
213 | { | 204 | { |
214 | int i; | ||
215 | struct ext4_group_desc * desc; | 205 | struct ext4_group_desc * desc; |
216 | struct buffer_head * bh = NULL; | 206 | struct buffer_head * bh = NULL; |
217 | ext4_fsblk_t bitmap_blk; | 207 | ext4_fsblk_t bitmap_blk; |
@@ -239,38 +229,7 @@ read_block_bitmap(struct super_block *sb, unsigned int block_group) | |||
239 | "Cannot read block bitmap - " | 229 | "Cannot read block bitmap - " |
240 | "block_group = %d, block_bitmap = %llu", | 230 | "block_group = %d, block_bitmap = %llu", |
241 | block_group, bitmap_blk); | 231 | block_group, bitmap_blk); |
242 | |||
243 | /* check whether block bitmap block number is set */ | ||
244 | if (!block_in_use(bitmap_blk, sb, bh->b_data)) { | ||
245 | /* bad block bitmap */ | ||
246 | goto error_out; | ||
247 | } | ||
248 | |||
249 | /* check whether the inode bitmap block number is set */ | ||
250 | bitmap_blk = ext4_inode_bitmap(sb, desc); | ||
251 | if (!block_in_use(bitmap_blk, sb, bh->b_data)) { | ||
252 | /* bad block bitmap */ | ||
253 | goto error_out; | ||
254 | } | ||
255 | /* check whether the inode table block number is set */ | ||
256 | bitmap_blk = ext4_inode_table(sb, desc); | ||
257 | for (i = 0; i < EXT4_SB(sb)->s_itb_per_group; i++, bitmap_blk++) { | ||
258 | if (!block_in_use(bitmap_blk, sb, bh->b_data)) { | ||
259 | /* bad block bitmap */ | ||
260 | goto error_out; | ||
261 | } | ||
262 | } | ||
263 | |||
264 | return bh; | 232 | return bh; |
265 | |||
266 | error_out: | ||
267 | brelse(bh); | ||
268 | ext4_error(sb, __FUNCTION__, | ||
269 | "Invalid block bitmap - " | ||
270 | "block_group = %d, block = %llu", | ||
271 | block_group, bitmap_blk); | ||
272 | return NULL; | ||
273 | |||
274 | } | 233 | } |
275 | /* | 234 | /* |
276 | * The reservation window structure operations | 235 | * The reservation window structure operations |
diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c index c04c7ccba9e3..e7f894bdb420 100644 --- a/fs/ext4/ioctl.c +++ b/fs/ext4/ioctl.c | |||
@@ -51,6 +51,11 @@ int ext4_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, | |||
51 | flags &= ~EXT4_DIRSYNC_FL; | 51 | flags &= ~EXT4_DIRSYNC_FL; |
52 | 52 | ||
53 | mutex_lock(&inode->i_mutex); | 53 | mutex_lock(&inode->i_mutex); |
54 | /* Is it quota file? Do not allow user to mess with it */ | ||
55 | if (IS_NOQUOTA(inode)) { | ||
56 | mutex_unlock(&inode->i_mutex); | ||
57 | return -EPERM; | ||
58 | } | ||
54 | oldflags = ei->i_flags; | 59 | oldflags = ei->i_flags; |
55 | 60 | ||
56 | /* The JOURNAL_DATA flag is modifiable only by root */ | 61 | /* The JOURNAL_DATA flag is modifiable only by root */ |
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index b11e9e2bcd01..8031dc0e24e5 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
@@ -686,13 +686,10 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs) | |||
686 | } | 686 | } |
687 | 687 | ||
688 | 688 | ||
689 | static struct dentry *ext4_get_dentry(struct super_block *sb, void *vobjp) | 689 | static struct inode *ext4_nfs_get_inode(struct super_block *sb, |
690 | u64 ino, u32 generation) | ||
690 | { | 691 | { |
691 | __u32 *objp = vobjp; | ||
692 | unsigned long ino = objp[0]; | ||
693 | __u32 generation = objp[1]; | ||
694 | struct inode *inode; | 692 | struct inode *inode; |
695 | struct dentry *result; | ||
696 | 693 | ||
697 | if (ino < EXT4_FIRST_INO(sb) && ino != EXT4_ROOT_INO) | 694 | if (ino < EXT4_FIRST_INO(sb) && ino != EXT4_ROOT_INO) |
698 | return ERR_PTR(-ESTALE); | 695 | return ERR_PTR(-ESTALE); |
@@ -715,15 +712,22 @@ static struct dentry *ext4_get_dentry(struct super_block *sb, void *vobjp) | |||
715 | iput(inode); | 712 | iput(inode); |
716 | return ERR_PTR(-ESTALE); | 713 | return ERR_PTR(-ESTALE); |
717 | } | 714 | } |
718 | /* now to find a dentry. | 715 | |
719 | * If possible, get a well-connected one | 716 | return inode; |
720 | */ | 717 | } |
721 | result = d_alloc_anon(inode); | 718 | |
722 | if (!result) { | 719 | static struct dentry *ext4_fh_to_dentry(struct super_block *sb, struct fid *fid, |
723 | iput(inode); | 720 | int fh_len, int fh_type) |
724 | return ERR_PTR(-ENOMEM); | 721 | { |
725 | } | 722 | return generic_fh_to_dentry(sb, fid, fh_len, fh_type, |
726 | return result; | 723 | ext4_nfs_get_inode); |
724 | } | ||
725 | |||
726 | static struct dentry *ext4_fh_to_parent(struct super_block *sb, struct fid *fid, | ||
727 | int fh_len, int fh_type) | ||
728 | { | ||
729 | return generic_fh_to_parent(sb, fid, fh_len, fh_type, | ||
730 | ext4_nfs_get_inode); | ||
727 | } | 731 | } |
728 | 732 | ||
729 | #ifdef CONFIG_QUOTA | 733 | #ifdef CONFIG_QUOTA |
@@ -792,9 +796,10 @@ static const struct super_operations ext4_sops = { | |||
792 | #endif | 796 | #endif |
793 | }; | 797 | }; |
794 | 798 | ||
795 | static struct export_operations ext4_export_ops = { | 799 | static const struct export_operations ext4_export_ops = { |
800 | .fh_to_dentry = ext4_fh_to_dentry, | ||
801 | .fh_to_parent = ext4_fh_to_parent, | ||
796 | .get_parent = ext4_get_parent, | 802 | .get_parent = ext4_get_parent, |
797 | .get_dentry = ext4_get_dentry, | ||
798 | }; | 803 | }; |
799 | 804 | ||
800 | enum { | 805 | enum { |
diff --git a/fs/fat/inode.c b/fs/fat/inode.c index c0c5e9c55b58..920a576e1c25 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c | |||
@@ -653,24 +653,15 @@ static const struct super_operations fat_sops = { | |||
653 | * of i_logstart is used to store the directory entry offset. | 653 | * of i_logstart is used to store the directory entry offset. |
654 | */ | 654 | */ |
655 | 655 | ||
656 | static struct dentry * | 656 | static struct dentry *fat_fh_to_dentry(struct super_block *sb, |
657 | fat_decode_fh(struct super_block *sb, __u32 *fh, int len, int fhtype, | 657 | struct fid *fid, int fh_len, int fh_type) |
658 | int (*acceptable)(void *context, struct dentry *de), | ||
659 | void *context) | ||
660 | { | ||
661 | if (fhtype != 3) | ||
662 | return ERR_PTR(-ESTALE); | ||
663 | if (len < 5) | ||
664 | return ERR_PTR(-ESTALE); | ||
665 | |||
666 | return sb->s_export_op->find_exported_dentry(sb, fh, NULL, acceptable, context); | ||
667 | } | ||
668 | |||
669 | static struct dentry *fat_get_dentry(struct super_block *sb, void *inump) | ||
670 | { | 658 | { |
671 | struct inode *inode = NULL; | 659 | struct inode *inode = NULL; |
672 | struct dentry *result; | 660 | struct dentry *result; |
673 | __u32 *fh = inump; | 661 | u32 *fh = fid->raw; |
662 | |||
663 | if (fh_len < 5 || fh_type != 3) | ||
664 | return NULL; | ||
674 | 665 | ||
675 | inode = iget(sb, fh[0]); | 666 | inode = iget(sb, fh[0]); |
676 | if (!inode || is_bad_inode(inode) || inode->i_generation != fh[1]) { | 667 | if (!inode || is_bad_inode(inode) || inode->i_generation != fh[1]) { |
@@ -783,10 +774,9 @@ out: | |||
783 | return parent; | 774 | return parent; |
784 | } | 775 | } |
785 | 776 | ||
786 | static struct export_operations fat_export_ops = { | 777 | static const struct export_operations fat_export_ops = { |
787 | .decode_fh = fat_decode_fh, | ||
788 | .encode_fh = fat_encode_fh, | 778 | .encode_fh = fat_encode_fh, |
789 | .get_dentry = fat_get_dentry, | 779 | .fh_to_dentry = fat_fh_to_dentry, |
790 | .get_parent = fat_get_parent, | 780 | .get_parent = fat_get_parent, |
791 | }; | 781 | }; |
792 | 782 | ||
diff --git a/fs/fcntl.c b/fs/fcntl.c index c9db73fc5e3d..8685263ccc4a 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/ptrace.h> | 18 | #include <linux/ptrace.h> |
19 | #include <linux/signal.h> | 19 | #include <linux/signal.h> |
20 | #include <linux/rcupdate.h> | 20 | #include <linux/rcupdate.h> |
21 | #include <linux/pid_namespace.h> | ||
21 | 22 | ||
22 | #include <asm/poll.h> | 23 | #include <asm/poll.h> |
23 | #include <asm/siginfo.h> | 24 | #include <asm/siginfo.h> |
@@ -292,7 +293,7 @@ int f_setown(struct file *filp, unsigned long arg, int force) | |||
292 | who = -who; | 293 | who = -who; |
293 | } | 294 | } |
294 | rcu_read_lock(); | 295 | rcu_read_lock(); |
295 | pid = find_pid(who); | 296 | pid = find_vpid(who); |
296 | result = __f_setown(filp, pid, type, force); | 297 | result = __f_setown(filp, pid, type, force); |
297 | rcu_read_unlock(); | 298 | rcu_read_unlock(); |
298 | return result; | 299 | return result; |
@@ -308,7 +309,7 @@ pid_t f_getown(struct file *filp) | |||
308 | { | 309 | { |
309 | pid_t pid; | 310 | pid_t pid; |
310 | read_lock(&filp->f_owner.lock); | 311 | read_lock(&filp->f_owner.lock); |
311 | pid = pid_nr(filp->f_owner.pid); | 312 | pid = pid_nr_ns(filp->f_owner.pid, current->nsproxy->pid_ns); |
312 | if (filp->f_owner.pid_type == PIDTYPE_PGID) | 313 | if (filp->f_owner.pid_type == PIDTYPE_PGID) |
313 | pid = -pid; | 314 | pid = -pid; |
314 | read_unlock(&filp->f_owner.lock); | 315 | read_unlock(&filp->f_owner.lock); |
diff --git a/fs/file_table.c b/fs/file_table.c index 3176fefc92e1..664e3f2309b8 100644 --- a/fs/file_table.c +++ b/fs/file_table.c | |||
@@ -323,12 +323,11 @@ void file_kill(struct file *file) | |||
323 | 323 | ||
324 | int fs_may_remount_ro(struct super_block *sb) | 324 | int fs_may_remount_ro(struct super_block *sb) |
325 | { | 325 | { |
326 | struct list_head *p; | 326 | struct file *file; |
327 | 327 | ||
328 | /* Check that no files are currently opened for writing. */ | 328 | /* Check that no files are currently opened for writing. */ |
329 | file_list_lock(); | 329 | file_list_lock(); |
330 | list_for_each(p, &sb->s_files) { | 330 | list_for_each_entry(file, &sb->s_files, f_u.fu_list) { |
331 | struct file *file = list_entry(p, struct file, f_u.fu_list); | ||
332 | struct inode *inode = file->f_path.dentry->d_inode; | 331 | struct inode *inode = file->f_path.dentry->d_inode; |
333 | 332 | ||
334 | /* File with pending delete? */ | 333 | /* File with pending delete? */ |
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index 686734ff973d..0fca82021d76 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c | |||
@@ -89,7 +89,7 @@ void __mark_inode_dirty(struct inode *inode, int flags) | |||
89 | if (inode->i_ino || strcmp(inode->i_sb->s_id, "bdev")) | 89 | if (inode->i_ino || strcmp(inode->i_sb->s_id, "bdev")) |
90 | printk(KERN_DEBUG | 90 | printk(KERN_DEBUG |
91 | "%s(%d): dirtied inode %lu (%s) on %s\n", | 91 | "%s(%d): dirtied inode %lu (%s) on %s\n", |
92 | current->comm, current->pid, inode->i_ino, | 92 | current->comm, task_pid_nr(current), inode->i_ino, |
93 | name, inode->i_sb->s_id); | 93 | name, inode->i_sb->s_id); |
94 | } | 94 | } |
95 | 95 | ||
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 3763757f9fe7..80d2f5292cf9 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c | |||
@@ -132,6 +132,21 @@ static void fuse_lookup_init(struct fuse_req *req, struct inode *dir, | |||
132 | req->out.args[0].value = outarg; | 132 | req->out.args[0].value = outarg; |
133 | } | 133 | } |
134 | 134 | ||
135 | static u64 fuse_get_attr_version(struct fuse_conn *fc) | ||
136 | { | ||
137 | u64 curr_version; | ||
138 | |||
139 | /* | ||
140 | * The spin lock isn't actually needed on 64bit archs, but we | ||
141 | * don't yet care too much about such optimizations. | ||
142 | */ | ||
143 | spin_lock(&fc->lock); | ||
144 | curr_version = fc->attr_version; | ||
145 | spin_unlock(&fc->lock); | ||
146 | |||
147 | return curr_version; | ||
148 | } | ||
149 | |||
135 | /* | 150 | /* |
136 | * Check whether the dentry is still valid | 151 | * Check whether the dentry is still valid |
137 | * | 152 | * |
@@ -171,9 +186,7 @@ static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd) | |||
171 | return 0; | 186 | return 0; |
172 | } | 187 | } |
173 | 188 | ||
174 | spin_lock(&fc->lock); | 189 | attr_version = fuse_get_attr_version(fc); |
175 | attr_version = fc->attr_version; | ||
176 | spin_unlock(&fc->lock); | ||
177 | 190 | ||
178 | parent = dget_parent(entry); | 191 | parent = dget_parent(entry); |
179 | fuse_lookup_init(req, parent->d_inode, entry, &outarg); | 192 | fuse_lookup_init(req, parent->d_inode, entry, &outarg); |
@@ -264,9 +277,7 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry, | |||
264 | return ERR_PTR(PTR_ERR(forget_req)); | 277 | return ERR_PTR(PTR_ERR(forget_req)); |
265 | } | 278 | } |
266 | 279 | ||
267 | spin_lock(&fc->lock); | 280 | attr_version = fuse_get_attr_version(fc); |
268 | attr_version = fc->attr_version; | ||
269 | spin_unlock(&fc->lock); | ||
270 | 281 | ||
271 | fuse_lookup_init(req, dir, entry, &outarg); | 282 | fuse_lookup_init(req, dir, entry, &outarg); |
272 | request_send(fc, req); | 283 | request_send(fc, req); |
@@ -646,6 +657,9 @@ static int fuse_rename(struct inode *olddir, struct dentry *oldent, | |||
646 | err = req->out.h.error; | 657 | err = req->out.h.error; |
647 | fuse_put_request(fc, req); | 658 | fuse_put_request(fc, req); |
648 | if (!err) { | 659 | if (!err) { |
660 | /* ctime changes */ | ||
661 | fuse_invalidate_attr(oldent->d_inode); | ||
662 | |||
649 | fuse_invalidate_attr(olddir); | 663 | fuse_invalidate_attr(olddir); |
650 | if (olddir != newdir) | 664 | if (olddir != newdir) |
651 | fuse_invalidate_attr(newdir); | 665 | fuse_invalidate_attr(newdir); |
@@ -733,9 +747,7 @@ static int fuse_do_getattr(struct inode *inode, struct kstat *stat, | |||
733 | if (IS_ERR(req)) | 747 | if (IS_ERR(req)) |
734 | return PTR_ERR(req); | 748 | return PTR_ERR(req); |
735 | 749 | ||
736 | spin_lock(&fc->lock); | 750 | attr_version = fuse_get_attr_version(fc); |
737 | attr_version = fc->attr_version; | ||
738 | spin_unlock(&fc->lock); | ||
739 | 751 | ||
740 | memset(&inarg, 0, sizeof(inarg)); | 752 | memset(&inarg, 0, sizeof(inarg)); |
741 | memset(&outarg, 0, sizeof(outarg)); | 753 | memset(&outarg, 0, sizeof(outarg)); |
@@ -775,6 +787,31 @@ static int fuse_do_getattr(struct inode *inode, struct kstat *stat, | |||
775 | return err; | 787 | return err; |
776 | } | 788 | } |
777 | 789 | ||
790 | int fuse_update_attributes(struct inode *inode, struct kstat *stat, | ||
791 | struct file *file, bool *refreshed) | ||
792 | { | ||
793 | struct fuse_inode *fi = get_fuse_inode(inode); | ||
794 | int err; | ||
795 | bool r; | ||
796 | |||
797 | if (fi->i_time < get_jiffies_64()) { | ||
798 | r = true; | ||
799 | err = fuse_do_getattr(inode, stat, file); | ||
800 | } else { | ||
801 | r = false; | ||
802 | err = 0; | ||
803 | if (stat) { | ||
804 | generic_fillattr(inode, stat); | ||
805 | stat->mode = fi->orig_i_mode; | ||
806 | } | ||
807 | } | ||
808 | |||
809 | if (refreshed != NULL) | ||
810 | *refreshed = r; | ||
811 | |||
812 | return err; | ||
813 | } | ||
814 | |||
778 | /* | 815 | /* |
779 | * Calling into a user-controlled filesystem gives the filesystem | 816 | * Calling into a user-controlled filesystem gives the filesystem |
780 | * daemon ptrace-like capabilities over the requester process. This | 817 | * daemon ptrace-like capabilities over the requester process. This |
@@ -862,14 +899,9 @@ static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd) | |||
862 | */ | 899 | */ |
863 | if ((fc->flags & FUSE_DEFAULT_PERMISSIONS) || | 900 | if ((fc->flags & FUSE_DEFAULT_PERMISSIONS) || |
864 | ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))) { | 901 | ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))) { |
865 | struct fuse_inode *fi = get_fuse_inode(inode); | 902 | err = fuse_update_attributes(inode, NULL, NULL, &refreshed); |
866 | if (fi->i_time < get_jiffies_64()) { | 903 | if (err) |
867 | err = fuse_do_getattr(inode, NULL, NULL); | 904 | return err; |
868 | if (err) | ||
869 | return err; | ||
870 | |||
871 | refreshed = true; | ||
872 | } | ||
873 | } | 905 | } |
874 | 906 | ||
875 | if (fc->flags & FUSE_DEFAULT_PERMISSIONS) { | 907 | if (fc->flags & FUSE_DEFAULT_PERMISSIONS) { |
@@ -935,7 +967,6 @@ static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir) | |||
935 | struct page *page; | 967 | struct page *page; |
936 | struct inode *inode = file->f_path.dentry->d_inode; | 968 | struct inode *inode = file->f_path.dentry->d_inode; |
937 | struct fuse_conn *fc = get_fuse_conn(inode); | 969 | struct fuse_conn *fc = get_fuse_conn(inode); |
938 | struct fuse_file *ff = file->private_data; | ||
939 | struct fuse_req *req; | 970 | struct fuse_req *req; |
940 | 971 | ||
941 | if (is_bad_inode(inode)) | 972 | if (is_bad_inode(inode)) |
@@ -952,7 +983,7 @@ static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir) | |||
952 | } | 983 | } |
953 | req->num_pages = 1; | 984 | req->num_pages = 1; |
954 | req->pages[0] = page; | 985 | req->pages[0] = page; |
955 | fuse_read_fill(req, ff, inode, file->f_pos, PAGE_SIZE, FUSE_READDIR); | 986 | fuse_read_fill(req, file, inode, file->f_pos, PAGE_SIZE, FUSE_READDIR); |
956 | request_send(fc, req); | 987 | request_send(fc, req); |
957 | nbytes = req->out.args[0].size; | 988 | nbytes = req->out.args[0].size; |
958 | err = req->out.h.error; | 989 | err = req->out.h.error; |
@@ -1173,22 +1204,12 @@ static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry, | |||
1173 | struct kstat *stat) | 1204 | struct kstat *stat) |
1174 | { | 1205 | { |
1175 | struct inode *inode = entry->d_inode; | 1206 | struct inode *inode = entry->d_inode; |
1176 | struct fuse_inode *fi = get_fuse_inode(inode); | ||
1177 | struct fuse_conn *fc = get_fuse_conn(inode); | 1207 | struct fuse_conn *fc = get_fuse_conn(inode); |
1178 | int err; | ||
1179 | 1208 | ||
1180 | if (!fuse_allow_task(fc, current)) | 1209 | if (!fuse_allow_task(fc, current)) |
1181 | return -EACCES; | 1210 | return -EACCES; |
1182 | 1211 | ||
1183 | if (fi->i_time < get_jiffies_64()) | 1212 | return fuse_update_attributes(inode, stat, NULL, NULL); |
1184 | err = fuse_do_getattr(inode, stat, NULL); | ||
1185 | else { | ||
1186 | err = 0; | ||
1187 | generic_fillattr(inode, stat); | ||
1188 | stat->mode = fi->orig_i_mode; | ||
1189 | } | ||
1190 | |||
1191 | return err; | ||
1192 | } | 1213 | } |
1193 | 1214 | ||
1194 | static int fuse_setxattr(struct dentry *entry, const char *name, | 1215 | static int fuse_setxattr(struct dentry *entry, const char *name, |
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 0fcdba9d47c0..bb05d227cf30 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c | |||
@@ -55,9 +55,10 @@ struct fuse_file *fuse_file_alloc(void) | |||
55 | if (!ff->reserved_req) { | 55 | if (!ff->reserved_req) { |
56 | kfree(ff); | 56 | kfree(ff); |
57 | ff = NULL; | 57 | ff = NULL; |
58 | } else { | ||
59 | INIT_LIST_HEAD(&ff->write_entry); | ||
60 | atomic_set(&ff->count, 0); | ||
58 | } | 61 | } |
59 | INIT_LIST_HEAD(&ff->write_entry); | ||
60 | atomic_set(&ff->count, 0); | ||
61 | } | 62 | } |
62 | return ff; | 63 | return ff; |
63 | } | 64 | } |
@@ -288,14 +289,16 @@ static int fuse_fsync(struct file *file, struct dentry *de, int datasync) | |||
288 | return fuse_fsync_common(file, de, datasync, 0); | 289 | return fuse_fsync_common(file, de, datasync, 0); |
289 | } | 290 | } |
290 | 291 | ||
291 | void fuse_read_fill(struct fuse_req *req, struct fuse_file *ff, | 292 | void fuse_read_fill(struct fuse_req *req, struct file *file, |
292 | struct inode *inode, loff_t pos, size_t count, int opcode) | 293 | struct inode *inode, loff_t pos, size_t count, int opcode) |
293 | { | 294 | { |
294 | struct fuse_read_in *inarg = &req->misc.read_in; | 295 | struct fuse_read_in *inarg = &req->misc.read_in; |
296 | struct fuse_file *ff = file->private_data; | ||
295 | 297 | ||
296 | inarg->fh = ff->fh; | 298 | inarg->fh = ff->fh; |
297 | inarg->offset = pos; | 299 | inarg->offset = pos; |
298 | inarg->size = count; | 300 | inarg->size = count; |
301 | inarg->flags = file->f_flags; | ||
299 | req->in.h.opcode = opcode; | 302 | req->in.h.opcode = opcode; |
300 | req->in.h.nodeid = get_node_id(inode); | 303 | req->in.h.nodeid = get_node_id(inode); |
301 | req->in.numargs = 1; | 304 | req->in.numargs = 1; |
@@ -312,9 +315,8 @@ static size_t fuse_send_read(struct fuse_req *req, struct file *file, | |||
312 | fl_owner_t owner) | 315 | fl_owner_t owner) |
313 | { | 316 | { |
314 | struct fuse_conn *fc = get_fuse_conn(inode); | 317 | struct fuse_conn *fc = get_fuse_conn(inode); |
315 | struct fuse_file *ff = file->private_data; | ||
316 | 318 | ||
317 | fuse_read_fill(req, ff, inode, pos, count, FUSE_READ); | 319 | fuse_read_fill(req, file, inode, pos, count, FUSE_READ); |
318 | if (owner != NULL) { | 320 | if (owner != NULL) { |
319 | struct fuse_read_in *inarg = &req->misc.read_in; | 321 | struct fuse_read_in *inarg = &req->misc.read_in; |
320 | 322 | ||
@@ -375,15 +377,16 @@ static void fuse_readpages_end(struct fuse_conn *fc, struct fuse_req *req) | |||
375 | fuse_put_request(fc, req); | 377 | fuse_put_request(fc, req); |
376 | } | 378 | } |
377 | 379 | ||
378 | static void fuse_send_readpages(struct fuse_req *req, struct fuse_file *ff, | 380 | static void fuse_send_readpages(struct fuse_req *req, struct file *file, |
379 | struct inode *inode) | 381 | struct inode *inode) |
380 | { | 382 | { |
381 | struct fuse_conn *fc = get_fuse_conn(inode); | 383 | struct fuse_conn *fc = get_fuse_conn(inode); |
382 | loff_t pos = page_offset(req->pages[0]); | 384 | loff_t pos = page_offset(req->pages[0]); |
383 | size_t count = req->num_pages << PAGE_CACHE_SHIFT; | 385 | size_t count = req->num_pages << PAGE_CACHE_SHIFT; |
384 | req->out.page_zeroing = 1; | 386 | req->out.page_zeroing = 1; |
385 | fuse_read_fill(req, ff, inode, pos, count, FUSE_READ); | 387 | fuse_read_fill(req, file, inode, pos, count, FUSE_READ); |
386 | if (fc->async_read) { | 388 | if (fc->async_read) { |
389 | struct fuse_file *ff = file->private_data; | ||
387 | req->ff = fuse_file_get(ff); | 390 | req->ff = fuse_file_get(ff); |
388 | req->end = fuse_readpages_end; | 391 | req->end = fuse_readpages_end; |
389 | request_send_background(fc, req); | 392 | request_send_background(fc, req); |
@@ -395,7 +398,7 @@ static void fuse_send_readpages(struct fuse_req *req, struct fuse_file *ff, | |||
395 | 398 | ||
396 | struct fuse_fill_data { | 399 | struct fuse_fill_data { |
397 | struct fuse_req *req; | 400 | struct fuse_req *req; |
398 | struct fuse_file *ff; | 401 | struct file *file; |
399 | struct inode *inode; | 402 | struct inode *inode; |
400 | }; | 403 | }; |
401 | 404 | ||
@@ -410,7 +413,7 @@ static int fuse_readpages_fill(void *_data, struct page *page) | |||
410 | (req->num_pages == FUSE_MAX_PAGES_PER_REQ || | 413 | (req->num_pages == FUSE_MAX_PAGES_PER_REQ || |
411 | (req->num_pages + 1) * PAGE_CACHE_SIZE > fc->max_read || | 414 | (req->num_pages + 1) * PAGE_CACHE_SIZE > fc->max_read || |
412 | req->pages[req->num_pages - 1]->index + 1 != page->index)) { | 415 | req->pages[req->num_pages - 1]->index + 1 != page->index)) { |
413 | fuse_send_readpages(req, data->ff, inode); | 416 | fuse_send_readpages(req, data->file, inode); |
414 | data->req = req = fuse_get_req(fc); | 417 | data->req = req = fuse_get_req(fc); |
415 | if (IS_ERR(req)) { | 418 | if (IS_ERR(req)) { |
416 | unlock_page(page); | 419 | unlock_page(page); |
@@ -434,7 +437,7 @@ static int fuse_readpages(struct file *file, struct address_space *mapping, | |||
434 | if (is_bad_inode(inode)) | 437 | if (is_bad_inode(inode)) |
435 | goto out; | 438 | goto out; |
436 | 439 | ||
437 | data.ff = file->private_data; | 440 | data.file = file; |
438 | data.inode = inode; | 441 | data.inode = inode; |
439 | data.req = fuse_get_req(fc); | 442 | data.req = fuse_get_req(fc); |
440 | err = PTR_ERR(data.req); | 443 | err = PTR_ERR(data.req); |
@@ -444,7 +447,7 @@ static int fuse_readpages(struct file *file, struct address_space *mapping, | |||
444 | err = read_cache_pages(mapping, pages, fuse_readpages_fill, &data); | 447 | err = read_cache_pages(mapping, pages, fuse_readpages_fill, &data); |
445 | if (!err) { | 448 | if (!err) { |
446 | if (data.req->num_pages) | 449 | if (data.req->num_pages) |
447 | fuse_send_readpages(data.req, data.ff, inode); | 450 | fuse_send_readpages(data.req, file, inode); |
448 | else | 451 | else |
449 | fuse_put_request(fc, data.req); | 452 | fuse_put_request(fc, data.req); |
450 | } | 453 | } |
@@ -452,11 +455,31 @@ out: | |||
452 | return err; | 455 | return err; |
453 | } | 456 | } |
454 | 457 | ||
455 | static void fuse_write_fill(struct fuse_req *req, struct fuse_file *ff, | 458 | static ssize_t fuse_file_aio_read(struct kiocb *iocb, const struct iovec *iov, |
459 | unsigned long nr_segs, loff_t pos) | ||
460 | { | ||
461 | struct inode *inode = iocb->ki_filp->f_mapping->host; | ||
462 | |||
463 | if (pos + iov_length(iov, nr_segs) > i_size_read(inode)) { | ||
464 | int err; | ||
465 | /* | ||
466 | * If trying to read past EOF, make sure the i_size | ||
467 | * attribute is up-to-date. | ||
468 | */ | ||
469 | err = fuse_update_attributes(inode, NULL, iocb->ki_filp, NULL); | ||
470 | if (err) | ||
471 | return err; | ||
472 | } | ||
473 | |||
474 | return generic_file_aio_read(iocb, iov, nr_segs, pos); | ||
475 | } | ||
476 | |||
477 | static void fuse_write_fill(struct fuse_req *req, struct file *file, | ||
456 | struct inode *inode, loff_t pos, size_t count, | 478 | struct inode *inode, loff_t pos, size_t count, |
457 | int writepage) | 479 | int writepage) |
458 | { | 480 | { |
459 | struct fuse_conn *fc = get_fuse_conn(inode); | 481 | struct fuse_conn *fc = get_fuse_conn(inode); |
482 | struct fuse_file *ff = file->private_data; | ||
460 | struct fuse_write_in *inarg = &req->misc.write.in; | 483 | struct fuse_write_in *inarg = &req->misc.write.in; |
461 | struct fuse_write_out *outarg = &req->misc.write.out; | 484 | struct fuse_write_out *outarg = &req->misc.write.out; |
462 | 485 | ||
@@ -465,6 +488,7 @@ static void fuse_write_fill(struct fuse_req *req, struct fuse_file *ff, | |||
465 | inarg->offset = pos; | 488 | inarg->offset = pos; |
466 | inarg->size = count; | 489 | inarg->size = count; |
467 | inarg->write_flags = writepage ? FUSE_WRITE_CACHE : 0; | 490 | inarg->write_flags = writepage ? FUSE_WRITE_CACHE : 0; |
491 | inarg->flags = file->f_flags; | ||
468 | req->in.h.opcode = FUSE_WRITE; | 492 | req->in.h.opcode = FUSE_WRITE; |
469 | req->in.h.nodeid = get_node_id(inode); | 493 | req->in.h.nodeid = get_node_id(inode); |
470 | req->in.argpages = 1; | 494 | req->in.argpages = 1; |
@@ -485,7 +509,7 @@ static size_t fuse_send_write(struct fuse_req *req, struct file *file, | |||
485 | fl_owner_t owner) | 509 | fl_owner_t owner) |
486 | { | 510 | { |
487 | struct fuse_conn *fc = get_fuse_conn(inode); | 511 | struct fuse_conn *fc = get_fuse_conn(inode); |
488 | fuse_write_fill(req, file->private_data, inode, pos, count, 0); | 512 | fuse_write_fill(req, file, inode, pos, count, 0); |
489 | if (owner != NULL) { | 513 | if (owner != NULL) { |
490 | struct fuse_write_in *inarg = &req->misc.write.in; | 514 | struct fuse_write_in *inarg = &req->misc.write.in; |
491 | inarg->write_flags |= FUSE_WRITE_LOCKOWNER; | 515 | inarg->write_flags |= FUSE_WRITE_LOCKOWNER; |
@@ -886,7 +910,7 @@ static sector_t fuse_bmap(struct address_space *mapping, sector_t block) | |||
886 | static const struct file_operations fuse_file_operations = { | 910 | static const struct file_operations fuse_file_operations = { |
887 | .llseek = generic_file_llseek, | 911 | .llseek = generic_file_llseek, |
888 | .read = do_sync_read, | 912 | .read = do_sync_read, |
889 | .aio_read = generic_file_aio_read, | 913 | .aio_read = fuse_file_aio_read, |
890 | .write = do_sync_write, | 914 | .write = do_sync_write, |
891 | .aio_write = generic_file_aio_write, | 915 | .aio_write = generic_file_aio_write, |
892 | .mmap = fuse_file_mmap, | 916 | .mmap = fuse_file_mmap, |
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index 6c5461de1a5f..3ab8a3048e8b 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h | |||
@@ -447,7 +447,7 @@ void fuse_send_forget(struct fuse_conn *fc, struct fuse_req *req, | |||
447 | /** | 447 | /** |
448 | * Initialize READ or READDIR request | 448 | * Initialize READ or READDIR request |
449 | */ | 449 | */ |
450 | void fuse_read_fill(struct fuse_req *req, struct fuse_file *ff, | 450 | void fuse_read_fill(struct fuse_req *req, struct file *file, |
451 | struct inode *inode, loff_t pos, size_t count, int opcode); | 451 | struct inode *inode, loff_t pos, size_t count, int opcode); |
452 | 452 | ||
453 | /** | 453 | /** |
@@ -593,3 +593,6 @@ int fuse_valid_type(int m); | |||
593 | int fuse_allow_task(struct fuse_conn *fc, struct task_struct *task); | 593 | int fuse_allow_task(struct fuse_conn *fc, struct task_struct *task); |
594 | 594 | ||
595 | u64 fuse_lock_owner_id(struct fuse_conn *fc, fl_owner_t id); | 595 | u64 fuse_lock_owner_id(struct fuse_conn *fc, fl_owner_t id); |
596 | |||
597 | int fuse_update_attributes(struct inode *inode, struct kstat *stat, | ||
598 | struct file *file, bool *refreshed); | ||
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 9a68d6970845..84f9f7dfdf5b 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c | |||
@@ -56,6 +56,7 @@ static struct inode *fuse_alloc_inode(struct super_block *sb) | |||
56 | fi->i_time = 0; | 56 | fi->i_time = 0; |
57 | fi->nodeid = 0; | 57 | fi->nodeid = 0; |
58 | fi->nlookup = 0; | 58 | fi->nlookup = 0; |
59 | fi->attr_version = 0; | ||
59 | INIT_LIST_HEAD(&fi->write_files); | 60 | INIT_LIST_HEAD(&fi->write_files); |
60 | fi->forget_req = fuse_request_alloc(); | 61 | fi->forget_req = fuse_request_alloc(); |
61 | if (!fi->forget_req) { | 62 | if (!fi->forget_req) { |
@@ -562,8 +563,7 @@ static void fuse_send_init(struct fuse_conn *fc, struct fuse_req *req) | |||
562 | arg->major = FUSE_KERNEL_VERSION; | 563 | arg->major = FUSE_KERNEL_VERSION; |
563 | arg->minor = FUSE_KERNEL_MINOR_VERSION; | 564 | arg->minor = FUSE_KERNEL_MINOR_VERSION; |
564 | arg->max_readahead = fc->bdi.ra_pages * PAGE_CACHE_SIZE; | 565 | arg->max_readahead = fc->bdi.ra_pages * PAGE_CACHE_SIZE; |
565 | arg->flags |= FUSE_ASYNC_READ | FUSE_POSIX_LOCKS | FUSE_FILE_OPS | | 566 | arg->flags |= FUSE_ASYNC_READ | FUSE_POSIX_LOCKS | FUSE_ATOMIC_O_TRUNC; |
566 | FUSE_ATOMIC_O_TRUNC; | ||
567 | req->in.h.opcode = FUSE_INIT; | 567 | req->in.h.opcode = FUSE_INIT; |
568 | req->in.numargs = 1; | 568 | req->in.numargs = 1; |
569 | req->in.args[0].size = sizeof(*arg); | 569 | req->in.args[0].size = sizeof(*arg); |
diff --git a/fs/gfs2/ops_export.c b/fs/gfs2/ops_export.c index e2d1347796a9..b9da62348a87 100644 --- a/fs/gfs2/ops_export.c +++ b/fs/gfs2/ops_export.c | |||
@@ -31,40 +31,6 @@ | |||
31 | #define GFS2_LARGE_FH_SIZE 8 | 31 | #define GFS2_LARGE_FH_SIZE 8 |
32 | #define GFS2_OLD_FH_SIZE 10 | 32 | #define GFS2_OLD_FH_SIZE 10 |
33 | 33 | ||
34 | static struct dentry *gfs2_decode_fh(struct super_block *sb, | ||
35 | __u32 *p, | ||
36 | int fh_len, | ||
37 | int fh_type, | ||
38 | int (*acceptable)(void *context, | ||
39 | struct dentry *dentry), | ||
40 | void *context) | ||
41 | { | ||
42 | __be32 *fh = (__force __be32 *)p; | ||
43 | struct gfs2_inum_host inum, parent; | ||
44 | |||
45 | memset(&parent, 0, sizeof(struct gfs2_inum)); | ||
46 | |||
47 | switch (fh_len) { | ||
48 | case GFS2_LARGE_FH_SIZE: | ||
49 | case GFS2_OLD_FH_SIZE: | ||
50 | parent.no_formal_ino = ((u64)be32_to_cpu(fh[4])) << 32; | ||
51 | parent.no_formal_ino |= be32_to_cpu(fh[5]); | ||
52 | parent.no_addr = ((u64)be32_to_cpu(fh[6])) << 32; | ||
53 | parent.no_addr |= be32_to_cpu(fh[7]); | ||
54 | case GFS2_SMALL_FH_SIZE: | ||
55 | inum.no_formal_ino = ((u64)be32_to_cpu(fh[0])) << 32; | ||
56 | inum.no_formal_ino |= be32_to_cpu(fh[1]); | ||
57 | inum.no_addr = ((u64)be32_to_cpu(fh[2])) << 32; | ||
58 | inum.no_addr |= be32_to_cpu(fh[3]); | ||
59 | break; | ||
60 | default: | ||
61 | return NULL; | ||
62 | } | ||
63 | |||
64 | return gfs2_export_ops.find_exported_dentry(sb, &inum, &parent, | ||
65 | acceptable, context); | ||
66 | } | ||
67 | |||
68 | static int gfs2_encode_fh(struct dentry *dentry, __u32 *p, int *len, | 34 | static int gfs2_encode_fh(struct dentry *dentry, __u32 *p, int *len, |
69 | int connectable) | 35 | int connectable) |
70 | { | 36 | { |
@@ -189,10 +155,10 @@ static struct dentry *gfs2_get_parent(struct dentry *child) | |||
189 | return dentry; | 155 | return dentry; |
190 | } | 156 | } |
191 | 157 | ||
192 | static struct dentry *gfs2_get_dentry(struct super_block *sb, void *inum_obj) | 158 | static struct dentry *gfs2_get_dentry(struct super_block *sb, |
159 | struct gfs2_inum_host *inum) | ||
193 | { | 160 | { |
194 | struct gfs2_sbd *sdp = sb->s_fs_info; | 161 | struct gfs2_sbd *sdp = sb->s_fs_info; |
195 | struct gfs2_inum_host *inum = inum_obj; | ||
196 | struct gfs2_holder i_gh, ri_gh, rgd_gh; | 162 | struct gfs2_holder i_gh, ri_gh, rgd_gh; |
197 | struct gfs2_rgrpd *rgd; | 163 | struct gfs2_rgrpd *rgd; |
198 | struct inode *inode; | 164 | struct inode *inode; |
@@ -289,11 +255,50 @@ fail: | |||
289 | return ERR_PTR(error); | 255 | return ERR_PTR(error); |
290 | } | 256 | } |
291 | 257 | ||
292 | struct export_operations gfs2_export_ops = { | 258 | static struct dentry *gfs2_fh_to_dentry(struct super_block *sb, struct fid *fid, |
293 | .decode_fh = gfs2_decode_fh, | 259 | int fh_len, int fh_type) |
260 | { | ||
261 | struct gfs2_inum_host this; | ||
262 | __be32 *fh = (__force __be32 *)fid->raw; | ||
263 | |||
264 | switch (fh_type) { | ||
265 | case GFS2_SMALL_FH_SIZE: | ||
266 | case GFS2_LARGE_FH_SIZE: | ||
267 | case GFS2_OLD_FH_SIZE: | ||
268 | this.no_formal_ino = ((u64)be32_to_cpu(fh[0])) << 32; | ||
269 | this.no_formal_ino |= be32_to_cpu(fh[1]); | ||
270 | this.no_addr = ((u64)be32_to_cpu(fh[2])) << 32; | ||
271 | this.no_addr |= be32_to_cpu(fh[3]); | ||
272 | return gfs2_get_dentry(sb, &this); | ||
273 | default: | ||
274 | return NULL; | ||
275 | } | ||
276 | } | ||
277 | |||
278 | static struct dentry *gfs2_fh_to_parent(struct super_block *sb, struct fid *fid, | ||
279 | int fh_len, int fh_type) | ||
280 | { | ||
281 | struct gfs2_inum_host parent; | ||
282 | __be32 *fh = (__force __be32 *)fid->raw; | ||
283 | |||
284 | switch (fh_type) { | ||
285 | case GFS2_LARGE_FH_SIZE: | ||
286 | case GFS2_OLD_FH_SIZE: | ||
287 | parent.no_formal_ino = ((u64)be32_to_cpu(fh[4])) << 32; | ||
288 | parent.no_formal_ino |= be32_to_cpu(fh[5]); | ||
289 | parent.no_addr = ((u64)be32_to_cpu(fh[6])) << 32; | ||
290 | parent.no_addr |= be32_to_cpu(fh[7]); | ||
291 | return gfs2_get_dentry(sb, &parent); | ||
292 | default: | ||
293 | return NULL; | ||
294 | } | ||
295 | } | ||
296 | |||
297 | const struct export_operations gfs2_export_ops = { | ||
294 | .encode_fh = gfs2_encode_fh, | 298 | .encode_fh = gfs2_encode_fh, |
299 | .fh_to_dentry = gfs2_fh_to_dentry, | ||
300 | .fh_to_parent = gfs2_fh_to_parent, | ||
295 | .get_name = gfs2_get_name, | 301 | .get_name = gfs2_get_name, |
296 | .get_parent = gfs2_get_parent, | 302 | .get_parent = gfs2_get_parent, |
297 | .get_dentry = gfs2_get_dentry, | ||
298 | }; | 303 | }; |
299 | 304 | ||
diff --git a/fs/gfs2/ops_fstype.h b/fs/gfs2/ops_fstype.h index 407029b3b2b3..da8490511836 100644 --- a/fs/gfs2/ops_fstype.h +++ b/fs/gfs2/ops_fstype.h | |||
@@ -14,6 +14,6 @@ | |||
14 | 14 | ||
15 | extern struct file_system_type gfs2_fs_type; | 15 | extern struct file_system_type gfs2_fs_type; |
16 | extern struct file_system_type gfs2meta_fs_type; | 16 | extern struct file_system_type gfs2meta_fs_type; |
17 | extern struct export_operations gfs2_export_ops; | 17 | extern const struct export_operations gfs2_export_ops; |
18 | 18 | ||
19 | #endif /* __OPS_FSTYPE_DOT_H__ */ | 19 | #endif /* __OPS_FSTYPE_DOT_H__ */ |
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index 12aca8ed605f..09ee07f02663 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c | |||
@@ -364,7 +364,6 @@ static void truncate_hugepages(struct inode *inode, loff_t lstart) | |||
364 | ++next; | 364 | ++next; |
365 | truncate_huge_page(page); | 365 | truncate_huge_page(page); |
366 | unlock_page(page); | 366 | unlock_page(page); |
367 | hugetlb_put_quota(mapping); | ||
368 | freed++; | 367 | freed++; |
369 | } | 368 | } |
370 | huge_pagevec_release(&pvec); | 369 | huge_pagevec_release(&pvec); |
@@ -859,15 +858,15 @@ out_free: | |||
859 | return -ENOMEM; | 858 | return -ENOMEM; |
860 | } | 859 | } |
861 | 860 | ||
862 | int hugetlb_get_quota(struct address_space *mapping) | 861 | int hugetlb_get_quota(struct address_space *mapping, long delta) |
863 | { | 862 | { |
864 | int ret = 0; | 863 | int ret = 0; |
865 | struct hugetlbfs_sb_info *sbinfo = HUGETLBFS_SB(mapping->host->i_sb); | 864 | struct hugetlbfs_sb_info *sbinfo = HUGETLBFS_SB(mapping->host->i_sb); |
866 | 865 | ||
867 | if (sbinfo->free_blocks > -1) { | 866 | if (sbinfo->free_blocks > -1) { |
868 | spin_lock(&sbinfo->stat_lock); | 867 | spin_lock(&sbinfo->stat_lock); |
869 | if (sbinfo->free_blocks > 0) | 868 | if (sbinfo->free_blocks - delta >= 0) |
870 | sbinfo->free_blocks--; | 869 | sbinfo->free_blocks -= delta; |
871 | else | 870 | else |
872 | ret = -ENOMEM; | 871 | ret = -ENOMEM; |
873 | spin_unlock(&sbinfo->stat_lock); | 872 | spin_unlock(&sbinfo->stat_lock); |
@@ -876,13 +875,13 @@ int hugetlb_get_quota(struct address_space *mapping) | |||
876 | return ret; | 875 | return ret; |
877 | } | 876 | } |
878 | 877 | ||
879 | void hugetlb_put_quota(struct address_space *mapping) | 878 | void hugetlb_put_quota(struct address_space *mapping, long delta) |
880 | { | 879 | { |
881 | struct hugetlbfs_sb_info *sbinfo = HUGETLBFS_SB(mapping->host->i_sb); | 880 | struct hugetlbfs_sb_info *sbinfo = HUGETLBFS_SB(mapping->host->i_sb); |
882 | 881 | ||
883 | if (sbinfo->free_blocks > -1) { | 882 | if (sbinfo->free_blocks > -1) { |
884 | spin_lock(&sbinfo->stat_lock); | 883 | spin_lock(&sbinfo->stat_lock); |
885 | sbinfo->free_blocks++; | 884 | sbinfo->free_blocks += delta; |
886 | spin_unlock(&sbinfo->stat_lock); | 885 | spin_unlock(&sbinfo->stat_lock); |
887 | } | 886 | } |
888 | } | 887 | } |
diff --git a/fs/inotify.c b/fs/inotify.c index 7457501b9565..2c5b92152876 100644 --- a/fs/inotify.c +++ b/fs/inotify.c | |||
@@ -667,6 +667,49 @@ out: | |||
667 | EXPORT_SYMBOL_GPL(inotify_add_watch); | 667 | EXPORT_SYMBOL_GPL(inotify_add_watch); |
668 | 668 | ||
669 | /** | 669 | /** |
670 | * inotify_clone_watch - put the watch next to existing one | ||
671 | * @old: already installed watch | ||
672 | * @new: new watch | ||
673 | * | ||
674 | * Caller must hold the inotify_mutex of inode we are dealing with; | ||
675 | * it is expected to remove the old watch before unlocking the inode. | ||
676 | */ | ||
677 | s32 inotify_clone_watch(struct inotify_watch *old, struct inotify_watch *new) | ||
678 | { | ||
679 | struct inotify_handle *ih = old->ih; | ||
680 | int ret = 0; | ||
681 | |||
682 | new->mask = old->mask; | ||
683 | new->ih = ih; | ||
684 | |||
685 | mutex_lock(&ih->mutex); | ||
686 | |||
687 | /* Initialize a new watch */ | ||
688 | ret = inotify_handle_get_wd(ih, new); | ||
689 | if (unlikely(ret)) | ||
690 | goto out; | ||
691 | ret = new->wd; | ||
692 | |||
693 | get_inotify_handle(ih); | ||
694 | |||
695 | new->inode = igrab(old->inode); | ||
696 | |||
697 | list_add(&new->h_list, &ih->watches); | ||
698 | list_add(&new->i_list, &old->inode->inotify_watches); | ||
699 | out: | ||
700 | mutex_unlock(&ih->mutex); | ||
701 | return ret; | ||
702 | } | ||
703 | |||
704 | void inotify_evict_watch(struct inotify_watch *watch) | ||
705 | { | ||
706 | get_inotify_watch(watch); | ||
707 | mutex_lock(&watch->ih->mutex); | ||
708 | inotify_remove_watch_locked(watch->ih, watch); | ||
709 | mutex_unlock(&watch->ih->mutex); | ||
710 | } | ||
711 | |||
712 | /** | ||
670 | * inotify_rm_wd - remove a watch from an inotify instance | 713 | * inotify_rm_wd - remove a watch from an inotify instance |
671 | * @ih: inotify handle | 714 | * @ih: inotify handle |
672 | * @wd: watch descriptor to remove | 715 | * @wd: watch descriptor to remove |
diff --git a/fs/ioprio.c b/fs/ioprio.c index 10d2c211d18b..e4e01bc7f338 100644 --- a/fs/ioprio.c +++ b/fs/ioprio.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/capability.h> | 25 | #include <linux/capability.h> |
26 | #include <linux/syscalls.h> | 26 | #include <linux/syscalls.h> |
27 | #include <linux/security.h> | 27 | #include <linux/security.h> |
28 | #include <linux/pid_namespace.h> | ||
28 | 29 | ||
29 | static int set_task_ioprio(struct task_struct *task, int ioprio) | 30 | static int set_task_ioprio(struct task_struct *task, int ioprio) |
30 | { | 31 | { |
@@ -77,6 +78,10 @@ asmlinkage long sys_ioprio_set(int which, int who, int ioprio) | |||
77 | if (!capable(CAP_SYS_ADMIN)) | 78 | if (!capable(CAP_SYS_ADMIN)) |
78 | return -EPERM; | 79 | return -EPERM; |
79 | break; | 80 | break; |
81 | case IOPRIO_CLASS_NONE: | ||
82 | if (data) | ||
83 | return -EINVAL; | ||
84 | break; | ||
80 | default: | 85 | default: |
81 | return -EINVAL; | 86 | return -EINVAL; |
82 | } | 87 | } |
@@ -93,7 +98,7 @@ asmlinkage long sys_ioprio_set(int which, int who, int ioprio) | |||
93 | if (!who) | 98 | if (!who) |
94 | p = current; | 99 | p = current; |
95 | else | 100 | else |
96 | p = find_task_by_pid(who); | 101 | p = find_task_by_vpid(who); |
97 | if (p) | 102 | if (p) |
98 | ret = set_task_ioprio(p, ioprio); | 103 | ret = set_task_ioprio(p, ioprio); |
99 | break; | 104 | break; |
@@ -101,7 +106,7 @@ asmlinkage long sys_ioprio_set(int which, int who, int ioprio) | |||
101 | if (!who) | 106 | if (!who) |
102 | pgrp = task_pgrp(current); | 107 | pgrp = task_pgrp(current); |
103 | else | 108 | else |
104 | pgrp = find_pid(who); | 109 | pgrp = find_vpid(who); |
105 | do_each_pid_task(pgrp, PIDTYPE_PGID, p) { | 110 | do_each_pid_task(pgrp, PIDTYPE_PGID, p) { |
106 | ret = set_task_ioprio(p, ioprio); | 111 | ret = set_task_ioprio(p, ioprio); |
107 | if (ret) | 112 | if (ret) |
@@ -180,7 +185,7 @@ asmlinkage long sys_ioprio_get(int which, int who) | |||
180 | if (!who) | 185 | if (!who) |
181 | p = current; | 186 | p = current; |
182 | else | 187 | else |
183 | p = find_task_by_pid(who); | 188 | p = find_task_by_vpid(who); |
184 | if (p) | 189 | if (p) |
185 | ret = get_task_ioprio(p); | 190 | ret = get_task_ioprio(p); |
186 | break; | 191 | break; |
@@ -188,7 +193,7 @@ asmlinkage long sys_ioprio_get(int which, int who) | |||
188 | if (!who) | 193 | if (!who) |
189 | pgrp = task_pgrp(current); | 194 | pgrp = task_pgrp(current); |
190 | else | 195 | else |
191 | pgrp = find_pid(who); | 196 | pgrp = find_vpid(who); |
192 | do_each_pid_task(pgrp, PIDTYPE_PGID, p) { | 197 | do_each_pid_task(pgrp, PIDTYPE_PGID, p) { |
193 | tmpio = get_task_ioprio(p); | 198 | tmpio = get_task_ioprio(p); |
194 | if (tmpio < 0) | 199 | if (tmpio < 0) |
diff --git a/fs/isofs/export.c b/fs/isofs/export.c index 4af856a7fda7..29f9753ae5e5 100644 --- a/fs/isofs/export.c +++ b/fs/isofs/export.c | |||
@@ -42,16 +42,6 @@ isofs_export_iget(struct super_block *sb, | |||
42 | return result; | 42 | return result; |
43 | } | 43 | } |
44 | 44 | ||
45 | static struct dentry * | ||
46 | isofs_export_get_dentry(struct super_block *sb, void *vobjp) | ||
47 | { | ||
48 | __u32 *objp = vobjp; | ||
49 | unsigned long block = objp[0]; | ||
50 | unsigned long offset = objp[1]; | ||
51 | __u32 generation = objp[2]; | ||
52 | return isofs_export_iget(sb, block, offset, generation); | ||
53 | } | ||
54 | |||
55 | /* This function is surprisingly simple. The trick is understanding | 45 | /* This function is surprisingly simple. The trick is understanding |
56 | * that "child" is always a directory. So, to find its parent, you | 46 | * that "child" is always a directory. So, to find its parent, you |
57 | * simply need to find its ".." entry, normalize its block and offset, | 47 | * simply need to find its ".." entry, normalize its block and offset, |
@@ -182,43 +172,44 @@ isofs_export_encode_fh(struct dentry *dentry, | |||
182 | return type; | 172 | return type; |
183 | } | 173 | } |
184 | 174 | ||
175 | struct isofs_fid { | ||
176 | u32 block; | ||
177 | u16 offset; | ||
178 | u16 parent_offset; | ||
179 | u32 generation; | ||
180 | u32 parent_block; | ||
181 | u32 parent_generation; | ||
182 | }; | ||
185 | 183 | ||
186 | static struct dentry * | 184 | static struct dentry *isofs_fh_to_dentry(struct super_block *sb, |
187 | isofs_export_decode_fh(struct super_block *sb, | 185 | struct fid *fid, int fh_len, int fh_type) |
188 | __u32 *fh32, | ||
189 | int fh_len, | ||
190 | int fileid_type, | ||
191 | int (*acceptable)(void *context, struct dentry *de), | ||
192 | void *context) | ||
193 | { | 186 | { |
194 | __u16 *fh16 = (__u16*)fh32; | 187 | struct isofs_fid *ifid = (struct isofs_fid *)fid; |
195 | __u32 child[3]; /* The child is what triggered all this. */ | ||
196 | __u32 parent[3]; /* The parent is just along for the ride. */ | ||
197 | 188 | ||
198 | if (fh_len < 3 || fileid_type > 2) | 189 | if (fh_len < 3 || fh_type > 2) |
199 | return NULL; | 190 | return NULL; |
200 | 191 | ||
201 | child[0] = fh32[0]; | 192 | return isofs_export_iget(sb, ifid->block, ifid->offset, |
202 | child[1] = fh16[2]; /* fh16 [sic] */ | 193 | ifid->generation); |
203 | child[2] = fh32[2]; | ||
204 | |||
205 | parent[0] = 0; | ||
206 | parent[1] = 0; | ||
207 | parent[2] = 0; | ||
208 | if (fileid_type == 2) { | ||
209 | if (fh_len > 2) parent[0] = fh32[3]; | ||
210 | parent[1] = fh16[3]; /* fh16 [sic] */ | ||
211 | if (fh_len > 4) parent[2] = fh32[4]; | ||
212 | } | ||
213 | |||
214 | return sb->s_export_op->find_exported_dentry(sb, child, parent, | ||
215 | acceptable, context); | ||
216 | } | 194 | } |
217 | 195 | ||
196 | static struct dentry *isofs_fh_to_parent(struct super_block *sb, | ||
197 | struct fid *fid, int fh_len, int fh_type) | ||
198 | { | ||
199 | struct isofs_fid *ifid = (struct isofs_fid *)fid; | ||
200 | |||
201 | if (fh_type != 2) | ||
202 | return NULL; | ||
203 | |||
204 | return isofs_export_iget(sb, | ||
205 | fh_len > 2 ? ifid->parent_block : 0, | ||
206 | ifid->parent_offset, | ||
207 | fh_len > 4 ? ifid->parent_generation : 0); | ||
208 | } | ||
218 | 209 | ||
219 | struct export_operations isofs_export_ops = { | 210 | const struct export_operations isofs_export_ops = { |
220 | .decode_fh = isofs_export_decode_fh, | ||
221 | .encode_fh = isofs_export_encode_fh, | 211 | .encode_fh = isofs_export_encode_fh, |
222 | .get_dentry = isofs_export_get_dentry, | 212 | .fh_to_dentry = isofs_fh_to_dentry, |
213 | .fh_to_parent = isofs_fh_to_parent, | ||
223 | .get_parent = isofs_export_get_parent, | 214 | .get_parent = isofs_export_get_parent, |
224 | }; | 215 | }; |
diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c index aa359a2e4ce6..09e3d306e96f 100644 --- a/fs/isofs/inode.c +++ b/fs/isofs/inode.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * (C) 1991 Linus Torvalds - minix filesystem | 4 | * (C) 1991 Linus Torvalds - minix filesystem |
5 | * 1992, 1993, 1994 Eric Youngdale Modified for ISO 9660 filesystem. | 5 | * 1992, 1993, 1994 Eric Youngdale Modified for ISO 9660 filesystem. |
6 | * 1994 Eberhard Moenkeberg - multi session handling. | 6 | * 1994 Eberhard Mönkeberg - multi session handling. |
7 | * 1995 Mark Dobie - allow mounting of some weird VideoCDs and PhotoCDs. | 7 | * 1995 Mark Dobie - allow mounting of some weird VideoCDs and PhotoCDs. |
8 | * 1997 Gordon Chaffee - Joliet CDs | 8 | * 1997 Gordon Chaffee - Joliet CDs |
9 | * 1998 Eric Lammerts - ISO 9660 Level 3 | 9 | * 1998 Eric Lammerts - ISO 9660 Level 3 |
diff --git a/fs/isofs/isofs.h b/fs/isofs/isofs.h index a07e67b1ea7f..f3213f9f89af 100644 --- a/fs/isofs/isofs.h +++ b/fs/isofs/isofs.h | |||
@@ -178,4 +178,4 @@ isofs_normalize_block_and_offset(struct iso_directory_record* de, | |||
178 | extern const struct inode_operations isofs_dir_inode_operations; | 178 | extern const struct inode_operations isofs_dir_inode_operations; |
179 | extern const struct file_operations isofs_dir_operations; | 179 | extern const struct file_operations isofs_dir_operations; |
180 | extern const struct address_space_operations isofs_symlink_aops; | 180 | extern const struct address_space_operations isofs_symlink_aops; |
181 | extern struct export_operations isofs_export_ops; | 181 | extern const struct export_operations isofs_export_ops; |
diff --git a/fs/jbd/checkpoint.c b/fs/jbd/checkpoint.c index 47552d4a6324..0f69c416eebc 100644 --- a/fs/jbd/checkpoint.c +++ b/fs/jbd/checkpoint.c | |||
@@ -602,15 +602,15 @@ int __journal_remove_checkpoint(struct journal_head *jh) | |||
602 | 602 | ||
603 | /* | 603 | /* |
604 | * There is one special case to worry about: if we have just pulled the | 604 | * There is one special case to worry about: if we have just pulled the |
605 | * buffer off a committing transaction's forget list, then even if the | 605 | * buffer off a running or committing transaction's checkpoing list, |
606 | * checkpoint list is empty, the transaction obviously cannot be | 606 | * then even if the checkpoint list is empty, the transaction obviously |
607 | * dropped! | 607 | * cannot be dropped! |
608 | * | 608 | * |
609 | * The locking here around j_committing_transaction is a bit sleazy. | 609 | * The locking here around t_state is a bit sleazy. |
610 | * See the comment at the end of journal_commit_transaction(). | 610 | * See the comment at the end of journal_commit_transaction(). |
611 | */ | 611 | */ |
612 | if (transaction == journal->j_committing_transaction) { | 612 | if (transaction->t_state != T_FINISHED) { |
613 | JBUFFER_TRACE(jh, "belongs to committing transaction"); | 613 | JBUFFER_TRACE(jh, "belongs to running/committing transaction"); |
614 | goto out; | 614 | goto out; |
615 | } | 615 | } |
616 | 616 | ||
diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c index a263d82761df..610264b99a8e 100644 --- a/fs/jbd/commit.c +++ b/fs/jbd/commit.c | |||
@@ -466,7 +466,7 @@ void journal_commit_transaction(journal_t *journal) | |||
466 | spin_unlock(&journal->j_list_lock); | 466 | spin_unlock(&journal->j_list_lock); |
467 | 467 | ||
468 | if (err) | 468 | if (err) |
469 | __journal_abort_hard(journal); | 469 | journal_abort(journal, err); |
470 | 470 | ||
471 | journal_write_revoke_records(journal, commit_transaction); | 471 | journal_write_revoke_records(journal, commit_transaction); |
472 | 472 | ||
@@ -524,7 +524,7 @@ void journal_commit_transaction(journal_t *journal) | |||
524 | 524 | ||
525 | descriptor = journal_get_descriptor_buffer(journal); | 525 | descriptor = journal_get_descriptor_buffer(journal); |
526 | if (!descriptor) { | 526 | if (!descriptor) { |
527 | __journal_abort_hard(journal); | 527 | journal_abort(journal, -EIO); |
528 | continue; | 528 | continue; |
529 | } | 529 | } |
530 | 530 | ||
@@ -557,7 +557,7 @@ void journal_commit_transaction(journal_t *journal) | |||
557 | and repeat this loop: we'll fall into the | 557 | and repeat this loop: we'll fall into the |
558 | refile-on-abort condition above. */ | 558 | refile-on-abort condition above. */ |
559 | if (err) { | 559 | if (err) { |
560 | __journal_abort_hard(journal); | 560 | journal_abort(journal, err); |
561 | continue; | 561 | continue; |
562 | } | 562 | } |
563 | 563 | ||
@@ -748,7 +748,7 @@ wait_for_iobuf: | |||
748 | err = -EIO; | 748 | err = -EIO; |
749 | 749 | ||
750 | if (err) | 750 | if (err) |
751 | __journal_abort_hard(journal); | 751 | journal_abort(journal, err); |
752 | 752 | ||
753 | /* End of a transaction! Finally, we can do checkpoint | 753 | /* End of a transaction! Finally, we can do checkpoint |
754 | processing: any buffers committed as a result of this | 754 | processing: any buffers committed as a result of this |
@@ -858,10 +858,10 @@ restart_loop: | |||
858 | } | 858 | } |
859 | spin_unlock(&journal->j_list_lock); | 859 | spin_unlock(&journal->j_list_lock); |
860 | /* | 860 | /* |
861 | * This is a bit sleazy. We borrow j_list_lock to protect | 861 | * This is a bit sleazy. We use j_list_lock to protect transition |
862 | * journal->j_committing_transaction in __journal_remove_checkpoint. | 862 | * of a transaction into T_FINISHED state and calling |
863 | * Really, __journal_remove_checkpoint should be using j_state_lock but | 863 | * __journal_drop_transaction(). Otherwise we could race with |
864 | * it's a bit hassle to hold that across __journal_remove_checkpoint | 864 | * other checkpointing code processing the transaction... |
865 | */ | 865 | */ |
866 | spin_lock(&journal->j_state_lock); | 866 | spin_lock(&journal->j_state_lock); |
867 | spin_lock(&journal->j_list_lock); | 867 | spin_lock(&journal->j_list_lock); |
diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c index 5d9fec0b7ebd..5d14243499d4 100644 --- a/fs/jbd/journal.c +++ b/fs/jbd/journal.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <linux/kthread.h> | 35 | #include <linux/kthread.h> |
36 | #include <linux/poison.h> | 36 | #include <linux/poison.h> |
37 | #include <linux/proc_fs.h> | 37 | #include <linux/proc_fs.h> |
38 | #include <linux/debugfs.h> | ||
38 | 39 | ||
39 | #include <asm/uaccess.h> | 40 | #include <asm/uaccess.h> |
40 | #include <asm/page.h> | 41 | #include <asm/page.h> |
@@ -654,10 +655,9 @@ static journal_t * journal_init_common (void) | |||
654 | journal_t *journal; | 655 | journal_t *journal; |
655 | int err; | 656 | int err; |
656 | 657 | ||
657 | journal = kmalloc(sizeof(*journal), GFP_KERNEL); | 658 | journal = kzalloc(sizeof(*journal), GFP_KERNEL); |
658 | if (!journal) | 659 | if (!journal) |
659 | goto fail; | 660 | goto fail; |
660 | memset(journal, 0, sizeof(*journal)); | ||
661 | 661 | ||
662 | init_waitqueue_head(&journal->j_wait_transaction_locked); | 662 | init_waitqueue_head(&journal->j_wait_transaction_locked); |
663 | init_waitqueue_head(&journal->j_wait_logspace); | 663 | init_waitqueue_head(&journal->j_wait_logspace); |
@@ -1852,64 +1852,41 @@ void journal_put_journal_head(struct journal_head *jh) | |||
1852 | } | 1852 | } |
1853 | 1853 | ||
1854 | /* | 1854 | /* |
1855 | * /proc tunables | 1855 | * debugfs tunables |
1856 | */ | 1856 | */ |
1857 | #if defined(CONFIG_JBD_DEBUG) | 1857 | #ifdef CONFIG_JBD_DEBUG |
1858 | int journal_enable_debug; | ||
1859 | EXPORT_SYMBOL(journal_enable_debug); | ||
1860 | #endif | ||
1861 | 1858 | ||
1862 | #if defined(CONFIG_JBD_DEBUG) && defined(CONFIG_PROC_FS) | 1859 | u8 journal_enable_debug __read_mostly; |
1860 | EXPORT_SYMBOL(journal_enable_debug); | ||
1863 | 1861 | ||
1864 | static struct proc_dir_entry *proc_jbd_debug; | 1862 | static struct dentry *jbd_debugfs_dir; |
1863 | static struct dentry *jbd_debug; | ||
1865 | 1864 | ||
1866 | static int read_jbd_debug(char *page, char **start, off_t off, | 1865 | static void __init jbd_create_debugfs_entry(void) |
1867 | int count, int *eof, void *data) | ||
1868 | { | 1866 | { |
1869 | int ret; | 1867 | jbd_debugfs_dir = debugfs_create_dir("jbd", NULL); |
1870 | 1868 | if (jbd_debugfs_dir) | |
1871 | ret = sprintf(page + off, "%d\n", journal_enable_debug); | 1869 | jbd_debug = debugfs_create_u8("jbd-debug", S_IRUGO, |
1872 | *eof = 1; | 1870 | jbd_debugfs_dir, |
1873 | return ret; | 1871 | &journal_enable_debug); |
1874 | } | 1872 | } |
1875 | 1873 | ||
1876 | static int write_jbd_debug(struct file *file, const char __user *buffer, | 1874 | static void __exit jbd_remove_debugfs_entry(void) |
1877 | unsigned long count, void *data) | ||
1878 | { | 1875 | { |
1879 | char buf[32]; | 1876 | debugfs_remove(jbd_debug); |
1880 | 1877 | debugfs_remove(jbd_debugfs_dir); | |
1881 | if (count > ARRAY_SIZE(buf) - 1) | ||
1882 | count = ARRAY_SIZE(buf) - 1; | ||
1883 | if (copy_from_user(buf, buffer, count)) | ||
1884 | return -EFAULT; | ||
1885 | buf[ARRAY_SIZE(buf) - 1] = '\0'; | ||
1886 | journal_enable_debug = simple_strtoul(buf, NULL, 10); | ||
1887 | return count; | ||
1888 | } | 1878 | } |
1889 | 1879 | ||
1890 | #define JBD_PROC_NAME "sys/fs/jbd-debug" | 1880 | #else |
1891 | 1881 | ||
1892 | static void __init create_jbd_proc_entry(void) | 1882 | static inline void jbd_create_debugfs_entry(void) |
1893 | { | 1883 | { |
1894 | proc_jbd_debug = create_proc_entry(JBD_PROC_NAME, 0644, NULL); | ||
1895 | if (proc_jbd_debug) { | ||
1896 | /* Why is this so hard? */ | ||
1897 | proc_jbd_debug->read_proc = read_jbd_debug; | ||
1898 | proc_jbd_debug->write_proc = write_jbd_debug; | ||
1899 | } | ||
1900 | } | 1884 | } |
1901 | 1885 | ||
1902 | static void __exit remove_jbd_proc_entry(void) | 1886 | static inline void jbd_remove_debugfs_entry(void) |
1903 | { | 1887 | { |
1904 | if (proc_jbd_debug) | ||
1905 | remove_proc_entry(JBD_PROC_NAME, NULL); | ||
1906 | } | 1888 | } |
1907 | 1889 | ||
1908 | #else | ||
1909 | |||
1910 | #define create_jbd_proc_entry() do {} while (0) | ||
1911 | #define remove_jbd_proc_entry() do {} while (0) | ||
1912 | |||
1913 | #endif | 1890 | #endif |
1914 | 1891 | ||
1915 | struct kmem_cache *jbd_handle_cache; | 1892 | struct kmem_cache *jbd_handle_cache; |
@@ -1966,7 +1943,7 @@ static int __init journal_init(void) | |||
1966 | ret = journal_init_caches(); | 1943 | ret = journal_init_caches(); |
1967 | if (ret != 0) | 1944 | if (ret != 0) |
1968 | journal_destroy_caches(); | 1945 | journal_destroy_caches(); |
1969 | create_jbd_proc_entry(); | 1946 | jbd_create_debugfs_entry(); |
1970 | return ret; | 1947 | return ret; |
1971 | } | 1948 | } |
1972 | 1949 | ||
@@ -1977,7 +1954,7 @@ static void __exit journal_exit(void) | |||
1977 | if (n) | 1954 | if (n) |
1978 | printk(KERN_EMERG "JBD: leaked %d journal_heads!\n", n); | 1955 | printk(KERN_EMERG "JBD: leaked %d journal_heads!\n", n); |
1979 | #endif | 1956 | #endif |
1980 | remove_jbd_proc_entry(); | 1957 | jbd_remove_debugfs_entry(); |
1981 | journal_destroy_caches(); | 1958 | journal_destroy_caches(); |
1982 | } | 1959 | } |
1983 | 1960 | ||
diff --git a/fs/jbd/recovery.c b/fs/jbd/recovery.c index 2a5f4b833e35..c5d9694b6a2f 100644 --- a/fs/jbd/recovery.c +++ b/fs/jbd/recovery.c | |||
@@ -250,10 +250,10 @@ int journal_recover(journal_t *journal) | |||
250 | if (!err) | 250 | if (!err) |
251 | err = do_one_pass(journal, &info, PASS_REPLAY); | 251 | err = do_one_pass(journal, &info, PASS_REPLAY); |
252 | 252 | ||
253 | jbd_debug(0, "JBD: recovery, exit status %d, " | 253 | jbd_debug(1, "JBD: recovery, exit status %d, " |
254 | "recovered transactions %u to %u\n", | 254 | "recovered transactions %u to %u\n", |
255 | err, info.start_transaction, info.end_transaction); | 255 | err, info.start_transaction, info.end_transaction); |
256 | jbd_debug(0, "JBD: Replayed %d and revoked %d/%d blocks\n", | 256 | jbd_debug(1, "JBD: Replayed %d and revoked %d/%d blocks\n", |
257 | info.nr_replays, info.nr_revoke_hits, info.nr_revokes); | 257 | info.nr_replays, info.nr_revoke_hits, info.nr_revokes); |
258 | 258 | ||
259 | /* Restart the log at the next transaction ID, thus invalidating | 259 | /* Restart the log at the next transaction ID, thus invalidating |
@@ -297,7 +297,7 @@ int journal_skip_recovery(journal_t *journal) | |||
297 | #ifdef CONFIG_JBD_DEBUG | 297 | #ifdef CONFIG_JBD_DEBUG |
298 | int dropped = info.end_transaction - be32_to_cpu(sb->s_sequence); | 298 | int dropped = info.end_transaction - be32_to_cpu(sb->s_sequence); |
299 | #endif | 299 | #endif |
300 | jbd_debug(0, | 300 | jbd_debug(1, |
301 | "JBD: ignoring %d transaction%s from the journal.\n", | 301 | "JBD: ignoring %d transaction%s from the journal.\n", |
302 | dropped, (dropped == 1) ? "" : "s"); | 302 | dropped, (dropped == 1) ? "" : "s"); |
303 | journal->j_transaction_sequence = ++info.end_transaction; | 303 | journal->j_transaction_sequence = ++info.end_transaction; |
diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c index 9841b1e5af03..08ff6c7028cc 100644 --- a/fs/jbd/transaction.c +++ b/fs/jbd/transaction.c | |||
@@ -96,13 +96,12 @@ static int start_this_handle(journal_t *journal, handle_t *handle) | |||
96 | 96 | ||
97 | alloc_transaction: | 97 | alloc_transaction: |
98 | if (!journal->j_running_transaction) { | 98 | if (!journal->j_running_transaction) { |
99 | new_transaction = kmalloc(sizeof(*new_transaction), | 99 | new_transaction = kzalloc(sizeof(*new_transaction), |
100 | GFP_NOFS|__GFP_NOFAIL); | 100 | GFP_NOFS|__GFP_NOFAIL); |
101 | if (!new_transaction) { | 101 | if (!new_transaction) { |
102 | ret = -ENOMEM; | 102 | ret = -ENOMEM; |
103 | goto out; | 103 | goto out; |
104 | } | 104 | } |
105 | memset(new_transaction, 0, sizeof(*new_transaction)); | ||
106 | } | 105 | } |
107 | 106 | ||
108 | jbd_debug(3, "New handle %p going live.\n", handle); | 107 | jbd_debug(3, "New handle %p going live.\n", handle); |
diff --git a/fs/jffs2/acl.c b/fs/jffs2/acl.c index 8ec9323e830a..77fc5838609c 100644 --- a/fs/jffs2/acl.c +++ b/fs/jffs2/acl.c | |||
@@ -228,11 +228,28 @@ struct posix_acl *jffs2_get_acl(struct inode *inode, int type) | |||
228 | return acl; | 228 | return acl; |
229 | } | 229 | } |
230 | 230 | ||
231 | static int __jffs2_set_acl(struct inode *inode, int xprefix, struct posix_acl *acl) | ||
232 | { | ||
233 | char *value = NULL; | ||
234 | size_t size = 0; | ||
235 | int rc; | ||
236 | |||
237 | if (acl) { | ||
238 | value = jffs2_acl_to_medium(acl, &size); | ||
239 | if (IS_ERR(value)) | ||
240 | return PTR_ERR(value); | ||
241 | } | ||
242 | rc = do_jffs2_setxattr(inode, xprefix, "", value, size, 0); | ||
243 | if (!value && rc == -ENODATA) | ||
244 | rc = 0; | ||
245 | kfree(value); | ||
246 | |||
247 | return rc; | ||
248 | } | ||
249 | |||
231 | static int jffs2_set_acl(struct inode *inode, int type, struct posix_acl *acl) | 250 | static int jffs2_set_acl(struct inode *inode, int type, struct posix_acl *acl) |
232 | { | 251 | { |
233 | struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); | 252 | struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); |
234 | size_t size = 0; | ||
235 | char *value = NULL; | ||
236 | int rc, xprefix; | 253 | int rc, xprefix; |
237 | 254 | ||
238 | if (S_ISLNK(inode->i_mode)) | 255 | if (S_ISLNK(inode->i_mode)) |
@@ -267,17 +284,7 @@ static int jffs2_set_acl(struct inode *inode, int type, struct posix_acl *acl) | |||
267 | default: | 284 | default: |
268 | return -EINVAL; | 285 | return -EINVAL; |
269 | } | 286 | } |
270 | if (acl) { | 287 | rc = __jffs2_set_acl(inode, xprefix, acl); |
271 | value = jffs2_acl_to_medium(acl, &size); | ||
272 | if (IS_ERR(value)) | ||
273 | return PTR_ERR(value); | ||
274 | } | ||
275 | |||
276 | rc = do_jffs2_setxattr(inode, xprefix, "", value, size, 0); | ||
277 | if (!value && rc == -ENODATA) | ||
278 | rc = 0; | ||
279 | if (value) | ||
280 | kfree(value); | ||
281 | if (!rc) { | 288 | if (!rc) { |
282 | switch(type) { | 289 | switch(type) { |
283 | case ACL_TYPE_ACCESS: | 290 | case ACL_TYPE_ACCESS: |
@@ -312,38 +319,60 @@ int jffs2_permission(struct inode *inode, int mask, struct nameidata *nd) | |||
312 | return generic_permission(inode, mask, jffs2_check_acl); | 319 | return generic_permission(inode, mask, jffs2_check_acl); |
313 | } | 320 | } |
314 | 321 | ||
315 | int jffs2_init_acl(struct inode *inode, struct posix_acl *acl) | 322 | int jffs2_init_acl_pre(struct inode *dir_i, struct inode *inode, int *i_mode) |
316 | { | 323 | { |
317 | struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); | 324 | struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); |
318 | struct posix_acl *clone; | 325 | struct posix_acl *acl, *clone; |
319 | mode_t mode; | 326 | int rc; |
320 | int rc = 0; | ||
321 | 327 | ||
322 | f->i_acl_access = JFFS2_ACL_NOT_CACHED; | 328 | f->i_acl_default = NULL; |
323 | f->i_acl_default = JFFS2_ACL_NOT_CACHED; | 329 | f->i_acl_access = NULL; |
330 | |||
331 | if (S_ISLNK(*i_mode)) | ||
332 | return 0; /* Symlink always has no-ACL */ | ||
333 | |||
334 | acl = jffs2_get_acl(dir_i, ACL_TYPE_DEFAULT); | ||
335 | if (IS_ERR(acl)) | ||
336 | return PTR_ERR(acl); | ||
337 | |||
338 | if (!acl) { | ||
339 | *i_mode &= ~current->fs->umask; | ||
340 | } else { | ||
341 | if (S_ISDIR(*i_mode)) | ||
342 | jffs2_iset_acl(inode, &f->i_acl_default, acl); | ||
324 | 343 | ||
325 | if (acl) { | ||
326 | if (S_ISDIR(inode->i_mode)) { | ||
327 | rc = jffs2_set_acl(inode, ACL_TYPE_DEFAULT, acl); | ||
328 | if (rc) | ||
329 | goto cleanup; | ||
330 | } | ||
331 | clone = posix_acl_clone(acl, GFP_KERNEL); | 344 | clone = posix_acl_clone(acl, GFP_KERNEL); |
332 | rc = -ENOMEM; | ||
333 | if (!clone) | 345 | if (!clone) |
334 | goto cleanup; | 346 | return -ENOMEM; |
335 | mode = inode->i_mode; | 347 | rc = posix_acl_create_masq(clone, (mode_t *)i_mode); |
336 | rc = posix_acl_create_masq(clone, &mode); | 348 | if (rc < 0) |
337 | if (rc >= 0) { | 349 | return rc; |
338 | inode->i_mode = mode; | 350 | if (rc > 0) |
339 | if (rc > 0) | 351 | jffs2_iset_acl(inode, &f->i_acl_access, clone); |
340 | rc = jffs2_set_acl(inode, ACL_TYPE_ACCESS, clone); | 352 | |
341 | } | ||
342 | posix_acl_release(clone); | 353 | posix_acl_release(clone); |
343 | } | 354 | } |
344 | cleanup: | 355 | return 0; |
345 | posix_acl_release(acl); | 356 | } |
346 | return rc; | 357 | |
358 | int jffs2_init_acl_post(struct inode *inode) | ||
359 | { | ||
360 | struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); | ||
361 | int rc; | ||
362 | |||
363 | if (f->i_acl_default) { | ||
364 | rc = __jffs2_set_acl(inode, JFFS2_XPREFIX_ACL_DEFAULT, f->i_acl_default); | ||
365 | if (rc) | ||
366 | return rc; | ||
367 | } | ||
368 | |||
369 | if (f->i_acl_access) { | ||
370 | rc = __jffs2_set_acl(inode, JFFS2_XPREFIX_ACL_ACCESS, f->i_acl_access); | ||
371 | if (rc) | ||
372 | return rc; | ||
373 | } | ||
374 | |||
375 | return 0; | ||
347 | } | 376 | } |
348 | 377 | ||
349 | void jffs2_clear_acl(struct jffs2_inode_info *f) | 378 | void jffs2_clear_acl(struct jffs2_inode_info *f) |
diff --git a/fs/jffs2/acl.h b/fs/jffs2/acl.h index 90a2dbf59051..76c6ebd1acd9 100644 --- a/fs/jffs2/acl.h +++ b/fs/jffs2/acl.h | |||
@@ -31,7 +31,8 @@ struct jffs2_acl_header { | |||
31 | extern struct posix_acl *jffs2_get_acl(struct inode *inode, int type); | 31 | extern struct posix_acl *jffs2_get_acl(struct inode *inode, int type); |
32 | extern int jffs2_permission(struct inode *, int, struct nameidata *); | 32 | extern int jffs2_permission(struct inode *, int, struct nameidata *); |
33 | extern int jffs2_acl_chmod(struct inode *); | 33 | extern int jffs2_acl_chmod(struct inode *); |
34 | extern int jffs2_init_acl(struct inode *, struct posix_acl *); | 34 | extern int jffs2_init_acl_pre(struct inode *, struct inode *, int *); |
35 | extern int jffs2_init_acl_post(struct inode *); | ||
35 | extern void jffs2_clear_acl(struct jffs2_inode_info *); | 36 | extern void jffs2_clear_acl(struct jffs2_inode_info *); |
36 | 37 | ||
37 | extern struct xattr_handler jffs2_acl_access_xattr_handler; | 38 | extern struct xattr_handler jffs2_acl_access_xattr_handler; |
@@ -39,10 +40,11 @@ extern struct xattr_handler jffs2_acl_default_xattr_handler; | |||
39 | 40 | ||
40 | #else | 41 | #else |
41 | 42 | ||
42 | #define jffs2_get_acl(inode, type) (NULL) | 43 | #define jffs2_get_acl(inode, type) (NULL) |
43 | #define jffs2_permission NULL | 44 | #define jffs2_permission (NULL) |
44 | #define jffs2_acl_chmod(inode) (0) | 45 | #define jffs2_acl_chmod(inode) (0) |
45 | #define jffs2_init_acl(inode,dir) (0) | 46 | #define jffs2_init_acl_pre(dir_i,inode,mode) (0) |
47 | #define jffs2_init_acl_post(inode) (0) | ||
46 | #define jffs2_clear_acl(f) | 48 | #define jffs2_clear_acl(f) |
47 | 49 | ||
48 | #endif /* CONFIG_JFFS2_FS_POSIX_ACL */ | 50 | #endif /* CONFIG_JFFS2_FS_POSIX_ACL */ |
diff --git a/fs/jffs2/background.c b/fs/jffs2/background.c index d568ae846741..8adebd3e43c6 100644 --- a/fs/jffs2/background.c +++ b/fs/jffs2/background.c | |||
@@ -105,7 +105,7 @@ static int jffs2_garbage_collect_thread(void *_c) | |||
105 | 105 | ||
106 | /* Put_super will send a SIGKILL and then wait on the sem. | 106 | /* Put_super will send a SIGKILL and then wait on the sem. |
107 | */ | 107 | */ |
108 | while (signal_pending(current)) { | 108 | while (signal_pending(current) || freezing(current)) { |
109 | siginfo_t info; | 109 | siginfo_t info; |
110 | unsigned long signr; | 110 | unsigned long signr; |
111 | 111 | ||
diff --git a/fs/jffs2/debug.h b/fs/jffs2/debug.h index 2a49f2c51a9f..4130adabd76e 100644 --- a/fs/jffs2/debug.h +++ b/fs/jffs2/debug.h | |||
@@ -80,28 +80,28 @@ | |||
80 | #define JFFS2_ERROR(fmt, ...) \ | 80 | #define JFFS2_ERROR(fmt, ...) \ |
81 | do { \ | 81 | do { \ |
82 | printk(JFFS2_ERR_MSG_PREFIX \ | 82 | printk(JFFS2_ERR_MSG_PREFIX \ |
83 | " (%d) %s: " fmt, current->pid, \ | 83 | " (%d) %s: " fmt, task_pid_nr(current), \ |
84 | __FUNCTION__ , ##__VA_ARGS__); \ | 84 | __FUNCTION__ , ##__VA_ARGS__); \ |
85 | } while(0) | 85 | } while(0) |
86 | 86 | ||
87 | #define JFFS2_WARNING(fmt, ...) \ | 87 | #define JFFS2_WARNING(fmt, ...) \ |
88 | do { \ | 88 | do { \ |
89 | printk(JFFS2_WARN_MSG_PREFIX \ | 89 | printk(JFFS2_WARN_MSG_PREFIX \ |
90 | " (%d) %s: " fmt, current->pid, \ | 90 | " (%d) %s: " fmt, task_pid_nr(current), \ |
91 | __FUNCTION__ , ##__VA_ARGS__); \ | 91 | __FUNCTION__ , ##__VA_ARGS__); \ |
92 | } while(0) | 92 | } while(0) |
93 | 93 | ||
94 | #define JFFS2_NOTICE(fmt, ...) \ | 94 | #define JFFS2_NOTICE(fmt, ...) \ |
95 | do { \ | 95 | do { \ |
96 | printk(JFFS2_NOTICE_MSG_PREFIX \ | 96 | printk(JFFS2_NOTICE_MSG_PREFIX \ |
97 | " (%d) %s: " fmt, current->pid, \ | 97 | " (%d) %s: " fmt, task_pid_nr(current), \ |
98 | __FUNCTION__ , ##__VA_ARGS__); \ | 98 | __FUNCTION__ , ##__VA_ARGS__); \ |
99 | } while(0) | 99 | } while(0) |
100 | 100 | ||
101 | #define JFFS2_DEBUG(fmt, ...) \ | 101 | #define JFFS2_DEBUG(fmt, ...) \ |
102 | do { \ | 102 | do { \ |
103 | printk(JFFS2_DBG_MSG_PREFIX \ | 103 | printk(JFFS2_DBG_MSG_PREFIX \ |
104 | " (%d) %s: " fmt, current->pid, \ | 104 | " (%d) %s: " fmt, task_pid_nr(current), \ |
105 | __FUNCTION__ , ##__VA_ARGS__); \ | 105 | __FUNCTION__ , ##__VA_ARGS__); \ |
106 | } while(0) | 106 | } while(0) |
107 | 107 | ||
diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c index 8353eb9c1799..787e392ffd41 100644 --- a/fs/jffs2/dir.c +++ b/fs/jffs2/dir.c | |||
@@ -182,7 +182,6 @@ static int jffs2_create(struct inode *dir_i, struct dentry *dentry, int mode, | |||
182 | struct jffs2_inode_info *f, *dir_f; | 182 | struct jffs2_inode_info *f, *dir_f; |
183 | struct jffs2_sb_info *c; | 183 | struct jffs2_sb_info *c; |
184 | struct inode *inode; | 184 | struct inode *inode; |
185 | struct posix_acl *acl; | ||
186 | int ret; | 185 | int ret; |
187 | 186 | ||
188 | ri = jffs2_alloc_raw_inode(); | 187 | ri = jffs2_alloc_raw_inode(); |
@@ -193,7 +192,7 @@ static int jffs2_create(struct inode *dir_i, struct dentry *dentry, int mode, | |||
193 | 192 | ||
194 | D1(printk(KERN_DEBUG "jffs2_create()\n")); | 193 | D1(printk(KERN_DEBUG "jffs2_create()\n")); |
195 | 194 | ||
196 | inode = jffs2_new_inode(dir_i, mode, ri, &acl); | 195 | inode = jffs2_new_inode(dir_i, mode, ri); |
197 | 196 | ||
198 | if (IS_ERR(inode)) { | 197 | if (IS_ERR(inode)) { |
199 | D1(printk(KERN_DEBUG "jffs2_new_inode() failed\n")); | 198 | D1(printk(KERN_DEBUG "jffs2_new_inode() failed\n")); |
@@ -211,14 +210,6 @@ static int jffs2_create(struct inode *dir_i, struct dentry *dentry, int mode, | |||
211 | 210 | ||
212 | ret = jffs2_do_create(c, dir_f, f, ri, | 211 | ret = jffs2_do_create(c, dir_f, f, ri, |
213 | dentry->d_name.name, dentry->d_name.len); | 212 | dentry->d_name.name, dentry->d_name.len); |
214 | |||
215 | if (ret) | ||
216 | goto fail_acl; | ||
217 | |||
218 | ret = jffs2_init_security(inode, dir_i); | ||
219 | if (ret) | ||
220 | goto fail_acl; | ||
221 | ret = jffs2_init_acl(inode, acl); | ||
222 | if (ret) | 213 | if (ret) |
223 | goto fail; | 214 | goto fail; |
224 | 215 | ||
@@ -231,8 +222,6 @@ static int jffs2_create(struct inode *dir_i, struct dentry *dentry, int mode, | |||
231 | inode->i_ino, inode->i_mode, inode->i_nlink, f->inocache->nlink, inode->i_mapping->nrpages)); | 222 | inode->i_ino, inode->i_mode, inode->i_nlink, f->inocache->nlink, inode->i_mapping->nrpages)); |
232 | return 0; | 223 | return 0; |
233 | 224 | ||
234 | fail_acl: | ||
235 | posix_acl_release(acl); | ||
236 | fail: | 225 | fail: |
237 | make_bad_inode(inode); | 226 | make_bad_inode(inode); |
238 | iput(inode); | 227 | iput(inode); |
@@ -309,7 +298,6 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char | |||
309 | struct jffs2_full_dirent *fd; | 298 | struct jffs2_full_dirent *fd; |
310 | int namelen; | 299 | int namelen; |
311 | uint32_t alloclen; | 300 | uint32_t alloclen; |
312 | struct posix_acl *acl; | ||
313 | int ret, targetlen = strlen(target); | 301 | int ret, targetlen = strlen(target); |
314 | 302 | ||
315 | /* FIXME: If you care. We'd need to use frags for the target | 303 | /* FIXME: If you care. We'd need to use frags for the target |
@@ -336,7 +324,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char | |||
336 | return ret; | 324 | return ret; |
337 | } | 325 | } |
338 | 326 | ||
339 | inode = jffs2_new_inode(dir_i, S_IFLNK | S_IRWXUGO, ri, &acl); | 327 | inode = jffs2_new_inode(dir_i, S_IFLNK | S_IRWXUGO, ri); |
340 | 328 | ||
341 | if (IS_ERR(inode)) { | 329 | if (IS_ERR(inode)) { |
342 | jffs2_free_raw_inode(ri); | 330 | jffs2_free_raw_inode(ri); |
@@ -366,7 +354,6 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char | |||
366 | up(&f->sem); | 354 | up(&f->sem); |
367 | jffs2_complete_reservation(c); | 355 | jffs2_complete_reservation(c); |
368 | jffs2_clear_inode(inode); | 356 | jffs2_clear_inode(inode); |
369 | posix_acl_release(acl); | ||
370 | return PTR_ERR(fn); | 357 | return PTR_ERR(fn); |
371 | } | 358 | } |
372 | 359 | ||
@@ -377,7 +364,6 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char | |||
377 | up(&f->sem); | 364 | up(&f->sem); |
378 | jffs2_complete_reservation(c); | 365 | jffs2_complete_reservation(c); |
379 | jffs2_clear_inode(inode); | 366 | jffs2_clear_inode(inode); |
380 | posix_acl_release(acl); | ||
381 | return -ENOMEM; | 367 | return -ENOMEM; |
382 | } | 368 | } |
383 | 369 | ||
@@ -395,10 +381,9 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char | |||
395 | ret = jffs2_init_security(inode, dir_i); | 381 | ret = jffs2_init_security(inode, dir_i); |
396 | if (ret) { | 382 | if (ret) { |
397 | jffs2_clear_inode(inode); | 383 | jffs2_clear_inode(inode); |
398 | posix_acl_release(acl); | ||
399 | return ret; | 384 | return ret; |
400 | } | 385 | } |
401 | ret = jffs2_init_acl(inode, acl); | 386 | ret = jffs2_init_acl_post(inode); |
402 | if (ret) { | 387 | if (ret) { |
403 | jffs2_clear_inode(inode); | 388 | jffs2_clear_inode(inode); |
404 | return ret; | 389 | return ret; |
@@ -476,7 +461,6 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode) | |||
476 | struct jffs2_full_dirent *fd; | 461 | struct jffs2_full_dirent *fd; |
477 | int namelen; | 462 | int namelen; |
478 | uint32_t alloclen; | 463 | uint32_t alloclen; |
479 | struct posix_acl *acl; | ||
480 | int ret; | 464 | int ret; |
481 | 465 | ||
482 | mode |= S_IFDIR; | 466 | mode |= S_IFDIR; |
@@ -499,7 +483,7 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode) | |||
499 | return ret; | 483 | return ret; |
500 | } | 484 | } |
501 | 485 | ||
502 | inode = jffs2_new_inode(dir_i, mode, ri, &acl); | 486 | inode = jffs2_new_inode(dir_i, mode, ri); |
503 | 487 | ||
504 | if (IS_ERR(inode)) { | 488 | if (IS_ERR(inode)) { |
505 | jffs2_free_raw_inode(ri); | 489 | jffs2_free_raw_inode(ri); |
@@ -526,7 +510,6 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode) | |||
526 | up(&f->sem); | 510 | up(&f->sem); |
527 | jffs2_complete_reservation(c); | 511 | jffs2_complete_reservation(c); |
528 | jffs2_clear_inode(inode); | 512 | jffs2_clear_inode(inode); |
529 | posix_acl_release(acl); | ||
530 | return PTR_ERR(fn); | 513 | return PTR_ERR(fn); |
531 | } | 514 | } |
532 | /* No data here. Only a metadata node, which will be | 515 | /* No data here. Only a metadata node, which will be |
@@ -540,10 +523,9 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode) | |||
540 | ret = jffs2_init_security(inode, dir_i); | 523 | ret = jffs2_init_security(inode, dir_i); |
541 | if (ret) { | 524 | if (ret) { |
542 | jffs2_clear_inode(inode); | 525 | jffs2_clear_inode(inode); |
543 | posix_acl_release(acl); | ||
544 | return ret; | 526 | return ret; |
545 | } | 527 | } |
546 | ret = jffs2_init_acl(inode, acl); | 528 | ret = jffs2_init_acl_post(inode); |
547 | if (ret) { | 529 | if (ret) { |
548 | jffs2_clear_inode(inode); | 530 | jffs2_clear_inode(inode); |
549 | return ret; | 531 | return ret; |
@@ -639,7 +621,6 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de | |||
639 | union jffs2_device_node dev; | 621 | union jffs2_device_node dev; |
640 | int devlen = 0; | 622 | int devlen = 0; |
641 | uint32_t alloclen; | 623 | uint32_t alloclen; |
642 | struct posix_acl *acl; | ||
643 | int ret; | 624 | int ret; |
644 | 625 | ||
645 | if (!new_valid_dev(rdev)) | 626 | if (!new_valid_dev(rdev)) |
@@ -666,7 +647,7 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de | |||
666 | return ret; | 647 | return ret; |
667 | } | 648 | } |
668 | 649 | ||
669 | inode = jffs2_new_inode(dir_i, mode, ri, &acl); | 650 | inode = jffs2_new_inode(dir_i, mode, ri); |
670 | 651 | ||
671 | if (IS_ERR(inode)) { | 652 | if (IS_ERR(inode)) { |
672 | jffs2_free_raw_inode(ri); | 653 | jffs2_free_raw_inode(ri); |
@@ -695,7 +676,6 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de | |||
695 | up(&f->sem); | 676 | up(&f->sem); |
696 | jffs2_complete_reservation(c); | 677 | jffs2_complete_reservation(c); |
697 | jffs2_clear_inode(inode); | 678 | jffs2_clear_inode(inode); |
698 | posix_acl_release(acl); | ||
699 | return PTR_ERR(fn); | 679 | return PTR_ERR(fn); |
700 | } | 680 | } |
701 | /* No data here. Only a metadata node, which will be | 681 | /* No data here. Only a metadata node, which will be |
@@ -709,10 +689,9 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de | |||
709 | ret = jffs2_init_security(inode, dir_i); | 689 | ret = jffs2_init_security(inode, dir_i); |
710 | if (ret) { | 690 | if (ret) { |
711 | jffs2_clear_inode(inode); | 691 | jffs2_clear_inode(inode); |
712 | posix_acl_release(acl); | ||
713 | return ret; | 692 | return ret; |
714 | } | 693 | } |
715 | ret = jffs2_init_acl(inode, acl); | 694 | ret = jffs2_init_acl_post(inode); |
716 | if (ret) { | 695 | if (ret) { |
717 | jffs2_clear_inode(inode); | 696 | jffs2_clear_inode(inode); |
718 | return ret; | 697 | return ret; |
diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c index 023a17539dd4..f9c5dd6f4b64 100644 --- a/fs/jffs2/file.c +++ b/fs/jffs2/file.c | |||
@@ -255,7 +255,7 @@ static int jffs2_write_end(struct file *filp, struct address_space *mapping, | |||
255 | _whole_ page. This helps to reduce the number of | 255 | _whole_ page. This helps to reduce the number of |
256 | nodes in files which have many short writes, like | 256 | nodes in files which have many short writes, like |
257 | syslog files. */ | 257 | syslog files. */ |
258 | start = aligned_start = 0; | 258 | aligned_start = 0; |
259 | } | 259 | } |
260 | 260 | ||
261 | ri = jffs2_alloc_raw_inode(); | 261 | ri = jffs2_alloc_raw_inode(); |
@@ -291,14 +291,11 @@ static int jffs2_write_end(struct file *filp, struct address_space *mapping, | |||
291 | } | 291 | } |
292 | 292 | ||
293 | /* Adjust writtenlen for the padding we did, so we don't confuse our caller */ | 293 | /* Adjust writtenlen for the padding we did, so we don't confuse our caller */ |
294 | if (writtenlen < (start&3)) | 294 | writtenlen -= min(writtenlen, (start - aligned_start)); |
295 | writtenlen = 0; | ||
296 | else | ||
297 | writtenlen -= (start&3); | ||
298 | 295 | ||
299 | if (writtenlen) { | 296 | if (writtenlen) { |
300 | if (inode->i_size < (pg->index << PAGE_CACHE_SHIFT) + start + writtenlen) { | 297 | if (inode->i_size < pos + writtenlen) { |
301 | inode->i_size = (pg->index << PAGE_CACHE_SHIFT) + start + writtenlen; | 298 | inode->i_size = pos + writtenlen; |
302 | inode->i_blocks = (inode->i_size + 511) >> 9; | 299 | inode->i_blocks = (inode->i_size + 511) >> 9; |
303 | 300 | ||
304 | inode->i_ctime = inode->i_mtime = ITIME(je32_to_cpu(ri->ctime)); | 301 | inode->i_ctime = inode->i_mtime = ITIME(je32_to_cpu(ri->ctime)); |
diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c index ed85f9afdbc8..d2e06f7ea96f 100644 --- a/fs/jffs2/fs.c +++ b/fs/jffs2/fs.c | |||
@@ -402,8 +402,7 @@ void jffs2_write_super (struct super_block *sb) | |||
402 | 402 | ||
403 | /* jffs2_new_inode: allocate a new inode and inocache, add it to the hash, | 403 | /* jffs2_new_inode: allocate a new inode and inocache, add it to the hash, |
404 | fill in the raw_inode while you're at it. */ | 404 | fill in the raw_inode while you're at it. */ |
405 | struct inode *jffs2_new_inode (struct inode *dir_i, int mode, struct jffs2_raw_inode *ri, | 405 | struct inode *jffs2_new_inode (struct inode *dir_i, int mode, struct jffs2_raw_inode *ri) |
406 | struct posix_acl **acl) | ||
407 | { | 406 | { |
408 | struct inode *inode; | 407 | struct inode *inode; |
409 | struct super_block *sb = dir_i->i_sb; | 408 | struct super_block *sb = dir_i->i_sb; |
@@ -438,19 +437,11 @@ struct inode *jffs2_new_inode (struct inode *dir_i, int mode, struct jffs2_raw_i | |||
438 | 437 | ||
439 | /* POSIX ACLs have to be processed now, at least partly. | 438 | /* POSIX ACLs have to be processed now, at least partly. |
440 | The umask is only applied if there's no default ACL */ | 439 | The umask is only applied if there's no default ACL */ |
441 | if (!S_ISLNK(mode)) { | 440 | ret = jffs2_init_acl_pre(dir_i, inode, &mode); |
442 | *acl = jffs2_get_acl(dir_i, ACL_TYPE_DEFAULT); | 441 | if (ret) { |
443 | if (IS_ERR(*acl)) { | 442 | make_bad_inode(inode); |
444 | make_bad_inode(inode); | 443 | iput(inode); |
445 | iput(inode); | 444 | return ERR_PTR(ret); |
446 | inode = (void *)*acl; | ||
447 | *acl = NULL; | ||
448 | return inode; | ||
449 | } | ||
450 | if (!(*acl)) | ||
451 | mode &= ~current->fs->umask; | ||
452 | } else { | ||
453 | *acl = NULL; | ||
454 | } | 445 | } |
455 | ret = jffs2_do_new_inode (c, f, mode, ri); | 446 | ret = jffs2_do_new_inode (c, f, mode, ri); |
456 | if (ret) { | 447 | if (ret) { |
diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h index f6743a915cf3..bf64686cf098 100644 --- a/fs/jffs2/os-linux.h +++ b/fs/jffs2/os-linux.h | |||
@@ -173,15 +173,13 @@ int jffs2_ioctl(struct inode *, struct file *, unsigned int, unsigned long); | |||
173 | extern const struct inode_operations jffs2_symlink_inode_operations; | 173 | extern const struct inode_operations jffs2_symlink_inode_operations; |
174 | 174 | ||
175 | /* fs.c */ | 175 | /* fs.c */ |
176 | struct posix_acl; | ||
177 | |||
178 | int jffs2_setattr (struct dentry *, struct iattr *); | 176 | int jffs2_setattr (struct dentry *, struct iattr *); |
179 | int jffs2_do_setattr (struct inode *, struct iattr *); | 177 | int jffs2_do_setattr (struct inode *, struct iattr *); |
180 | void jffs2_read_inode (struct inode *); | 178 | void jffs2_read_inode (struct inode *); |
181 | void jffs2_clear_inode (struct inode *); | 179 | void jffs2_clear_inode (struct inode *); |
182 | void jffs2_dirty_inode(struct inode *inode); | 180 | void jffs2_dirty_inode(struct inode *inode); |
183 | struct inode *jffs2_new_inode (struct inode *dir_i, int mode, | 181 | struct inode *jffs2_new_inode (struct inode *dir_i, int mode, |
184 | struct jffs2_raw_inode *ri, struct posix_acl **acl); | 182 | struct jffs2_raw_inode *ri); |
185 | int jffs2_statfs (struct dentry *, struct kstatfs *); | 183 | int jffs2_statfs (struct dentry *, struct kstatfs *); |
186 | void jffs2_write_super (struct super_block *); | 184 | void jffs2_write_super (struct super_block *); |
187 | int jffs2_remount_fs (struct super_block *, int *, char *); | 185 | int jffs2_remount_fs (struct super_block *, int *, char *); |
diff --git a/fs/jffs2/write.c b/fs/jffs2/write.c index 2f5695446d0f..147e2cbee9e4 100644 --- a/fs/jffs2/write.c +++ b/fs/jffs2/write.c | |||
@@ -465,6 +465,14 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str | |||
465 | 465 | ||
466 | up(&f->sem); | 466 | up(&f->sem); |
467 | jffs2_complete_reservation(c); | 467 | jffs2_complete_reservation(c); |
468 | |||
469 | ret = jffs2_init_security(&f->vfs_inode, &dir_f->vfs_inode); | ||
470 | if (ret) | ||
471 | return ret; | ||
472 | ret = jffs2_init_acl_post(&f->vfs_inode); | ||
473 | if (ret) | ||
474 | return ret; | ||
475 | |||
468 | ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen, | 476 | ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen, |
469 | ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); | 477 | ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); |
470 | 478 | ||
diff --git a/fs/jfs/ioctl.c b/fs/jfs/ioctl.c index 3c8663bea98c..dfda12a073e1 100644 --- a/fs/jfs/ioctl.c +++ b/fs/jfs/ioctl.c | |||
@@ -79,6 +79,9 @@ int jfs_ioctl(struct inode * inode, struct file * filp, unsigned int cmd, | |||
79 | if (!S_ISDIR(inode->i_mode)) | 79 | if (!S_ISDIR(inode->i_mode)) |
80 | flags &= ~JFS_DIRSYNC_FL; | 80 | flags &= ~JFS_DIRSYNC_FL; |
81 | 81 | ||
82 | /* Is it quota file? Do not allow user to mess with it */ | ||
83 | if (IS_NOQUOTA(inode)) | ||
84 | return -EPERM; | ||
82 | jfs_get_inode_flags(jfs_inode); | 85 | jfs_get_inode_flags(jfs_inode); |
83 | oldflags = jfs_inode->mode2; | 86 | oldflags = jfs_inode->mode2; |
84 | 87 | ||
diff --git a/fs/jfs/jfs_dtree.c b/fs/jfs/jfs_dtree.c index df0b8535de84..df25ecc418af 100644 --- a/fs/jfs/jfs_dtree.c +++ b/fs/jfs/jfs_dtree.c | |||
@@ -773,7 +773,7 @@ int dtSearch(struct inode *ip, struct component_name * key, ino_t * data, | |||
773 | getChild: | 773 | getChild: |
774 | /* update max. number of pages to split */ | 774 | /* update max. number of pages to split */ |
775 | if (BT_STACK_FULL(btstack)) { | 775 | if (BT_STACK_FULL(btstack)) { |
776 | /* Something's corrupted, mark filesytem dirty so | 776 | /* Something's corrupted, mark filesystem dirty so |
777 | * chkdsk will fix it. | 777 | * chkdsk will fix it. |
778 | */ | 778 | */ |
779 | jfs_error(sb, "stack overrun in dtSearch!"); | 779 | jfs_error(sb, "stack overrun in dtSearch!"); |
diff --git a/fs/jfs/jfs_inode.h b/fs/jfs/jfs_inode.h index f0ec72b263f1..8e2cf2cde185 100644 --- a/fs/jfs/jfs_inode.h +++ b/fs/jfs/jfs_inode.h | |||
@@ -18,6 +18,8 @@ | |||
18 | #ifndef _H_JFS_INODE | 18 | #ifndef _H_JFS_INODE |
19 | #define _H_JFS_INODE | 19 | #define _H_JFS_INODE |
20 | 20 | ||
21 | struct fid; | ||
22 | |||
21 | extern struct inode *ialloc(struct inode *, umode_t); | 23 | extern struct inode *ialloc(struct inode *, umode_t); |
22 | extern int jfs_fsync(struct file *, struct dentry *, int); | 24 | extern int jfs_fsync(struct file *, struct dentry *, int); |
23 | extern int jfs_ioctl(struct inode *, struct file *, | 25 | extern int jfs_ioctl(struct inode *, struct file *, |
@@ -32,7 +34,10 @@ extern void jfs_truncate_nolock(struct inode *, loff_t); | |||
32 | extern void jfs_free_zero_link(struct inode *); | 34 | extern void jfs_free_zero_link(struct inode *); |
33 | extern struct dentry *jfs_get_parent(struct dentry *dentry); | 35 | extern struct dentry *jfs_get_parent(struct dentry *dentry); |
34 | extern void jfs_get_inode_flags(struct jfs_inode_info *); | 36 | extern void jfs_get_inode_flags(struct jfs_inode_info *); |
35 | extern struct dentry *jfs_get_dentry(struct super_block *sb, void *vobjp); | 37 | extern struct dentry *jfs_fh_to_dentry(struct super_block *sb, struct fid *fid, |
38 | int fh_len, int fh_type); | ||
39 | extern struct dentry *jfs_fh_to_parent(struct super_block *sb, struct fid *fid, | ||
40 | int fh_len, int fh_type); | ||
36 | extern void jfs_set_inode_flags(struct inode *); | 41 | extern void jfs_set_inode_flags(struct inode *); |
37 | extern int jfs_get_block(struct inode *, sector_t, struct buffer_head *, int); | 42 | extern int jfs_get_block(struct inode *, sector_t, struct buffer_head *, int); |
38 | 43 | ||
diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c index 932797ba433b..4e0a8493cef6 100644 --- a/fs/jfs/namei.c +++ b/fs/jfs/namei.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/fs.h> | 20 | #include <linux/fs.h> |
21 | #include <linux/ctype.h> | 21 | #include <linux/ctype.h> |
22 | #include <linux/quotaops.h> | 22 | #include <linux/quotaops.h> |
23 | #include <linux/exportfs.h> | ||
23 | #include "jfs_incore.h" | 24 | #include "jfs_incore.h" |
24 | #include "jfs_superblock.h" | 25 | #include "jfs_superblock.h" |
25 | #include "jfs_inode.h" | 26 | #include "jfs_inode.h" |
@@ -1477,13 +1478,10 @@ static struct dentry *jfs_lookup(struct inode *dip, struct dentry *dentry, struc | |||
1477 | return dentry; | 1478 | return dentry; |
1478 | } | 1479 | } |
1479 | 1480 | ||
1480 | struct dentry *jfs_get_dentry(struct super_block *sb, void *vobjp) | 1481 | static struct inode *jfs_nfs_get_inode(struct super_block *sb, |
1482 | u64 ino, u32 generation) | ||
1481 | { | 1483 | { |
1482 | __u32 *objp = vobjp; | ||
1483 | unsigned long ino = objp[0]; | ||
1484 | __u32 generation = objp[1]; | ||
1485 | struct inode *inode; | 1484 | struct inode *inode; |
1486 | struct dentry *result; | ||
1487 | 1485 | ||
1488 | if (ino == 0) | 1486 | if (ino == 0) |
1489 | return ERR_PTR(-ESTALE); | 1487 | return ERR_PTR(-ESTALE); |
@@ -1493,20 +1491,25 @@ struct dentry *jfs_get_dentry(struct super_block *sb, void *vobjp) | |||
1493 | 1491 | ||
1494 | if (is_bad_inode(inode) || | 1492 | if (is_bad_inode(inode) || |
1495 | (generation && inode->i_generation != generation)) { | 1493 | (generation && inode->i_generation != generation)) { |
1496 | result = ERR_PTR(-ESTALE); | 1494 | iput(inode); |
1497 | goto out_iput; | 1495 | return ERR_PTR(-ESTALE); |
1498 | } | 1496 | } |
1499 | 1497 | ||
1500 | result = d_alloc_anon(inode); | 1498 | return inode; |
1501 | if (!result) { | 1499 | } |
1502 | result = ERR_PTR(-ENOMEM); | ||
1503 | goto out_iput; | ||
1504 | } | ||
1505 | return result; | ||
1506 | 1500 | ||
1507 | out_iput: | 1501 | struct dentry *jfs_fh_to_dentry(struct super_block *sb, struct fid *fid, |
1508 | iput(inode); | 1502 | int fh_len, int fh_type) |
1509 | return result; | 1503 | { |
1504 | return generic_fh_to_dentry(sb, fid, fh_len, fh_type, | ||
1505 | jfs_nfs_get_inode); | ||
1506 | } | ||
1507 | |||
1508 | struct dentry *jfs_fh_to_parent(struct super_block *sb, struct fid *fid, | ||
1509 | int fh_len, int fh_type) | ||
1510 | { | ||
1511 | return generic_fh_to_parent(sb, fid, fh_len, fh_type, | ||
1512 | jfs_nfs_get_inode); | ||
1510 | } | 1513 | } |
1511 | 1514 | ||
1512 | struct dentry *jfs_get_parent(struct dentry *dentry) | 1515 | struct dentry *jfs_get_parent(struct dentry *dentry) |
diff --git a/fs/jfs/super.c b/fs/jfs/super.c index cff60c171943..314bb4ff1ba8 100644 --- a/fs/jfs/super.c +++ b/fs/jfs/super.c | |||
@@ -48,7 +48,7 @@ MODULE_LICENSE("GPL"); | |||
48 | static struct kmem_cache * jfs_inode_cachep; | 48 | static struct kmem_cache * jfs_inode_cachep; |
49 | 49 | ||
50 | static const struct super_operations jfs_super_operations; | 50 | static const struct super_operations jfs_super_operations; |
51 | static struct export_operations jfs_export_operations; | 51 | static const struct export_operations jfs_export_operations; |
52 | static struct file_system_type jfs_fs_type; | 52 | static struct file_system_type jfs_fs_type; |
53 | 53 | ||
54 | #define MAX_COMMIT_THREADS 64 | 54 | #define MAX_COMMIT_THREADS 64 |
@@ -737,8 +737,9 @@ static const struct super_operations jfs_super_operations = { | |||
737 | #endif | 737 | #endif |
738 | }; | 738 | }; |
739 | 739 | ||
740 | static struct export_operations jfs_export_operations = { | 740 | static const struct export_operations jfs_export_operations = { |
741 | .get_dentry = jfs_get_dentry, | 741 | .fh_to_dentry = jfs_fh_to_dentry, |
742 | .fh_to_parent = jfs_fh_to_parent, | ||
742 | .get_parent = jfs_get_parent, | 743 | .get_parent = jfs_get_parent, |
743 | }; | 744 | }; |
744 | 745 | ||
diff --git a/fs/libfs.c b/fs/libfs.c index ae51481e45e5..6e68b700958d 100644 --- a/fs/libfs.c +++ b/fs/libfs.c | |||
@@ -8,6 +8,7 @@ | |||
8 | #include <linux/mount.h> | 8 | #include <linux/mount.h> |
9 | #include <linux/vfs.h> | 9 | #include <linux/vfs.h> |
10 | #include <linux/mutex.h> | 10 | #include <linux/mutex.h> |
11 | #include <linux/exportfs.h> | ||
11 | 12 | ||
12 | #include <asm/uaccess.h> | 13 | #include <asm/uaccess.h> |
13 | 14 | ||
@@ -678,6 +679,93 @@ out: | |||
678 | return ret; | 679 | return ret; |
679 | } | 680 | } |
680 | 681 | ||
682 | /* | ||
683 | * This is what d_alloc_anon should have been. Once the exportfs | ||
684 | * argument transition has been finished I will update d_alloc_anon | ||
685 | * to this prototype and this wrapper will go away. --hch | ||
686 | */ | ||
687 | static struct dentry *exportfs_d_alloc(struct inode *inode) | ||
688 | { | ||
689 | struct dentry *dentry; | ||
690 | |||
691 | if (!inode) | ||
692 | return NULL; | ||
693 | if (IS_ERR(inode)) | ||
694 | return ERR_PTR(PTR_ERR(inode)); | ||
695 | |||
696 | dentry = d_alloc_anon(inode); | ||
697 | if (!dentry) { | ||
698 | iput(inode); | ||
699 | dentry = ERR_PTR(-ENOMEM); | ||
700 | } | ||
701 | return dentry; | ||
702 | } | ||
703 | |||
704 | /** | ||
705 | * generic_fh_to_dentry - generic helper for the fh_to_dentry export operation | ||
706 | * @sb: filesystem to do the file handle conversion on | ||
707 | * @fid: file handle to convert | ||
708 | * @fh_len: length of the file handle in bytes | ||
709 | * @fh_type: type of file handle | ||
710 | * @get_inode: filesystem callback to retrieve inode | ||
711 | * | ||
712 | * This function decodes @fid as long as it has one of the well-known | ||
713 | * Linux filehandle types and calls @get_inode on it to retrieve the | ||
714 | * inode for the object specified in the file handle. | ||
715 | */ | ||
716 | struct dentry *generic_fh_to_dentry(struct super_block *sb, struct fid *fid, | ||
717 | int fh_len, int fh_type, struct inode *(*get_inode) | ||
718 | (struct super_block *sb, u64 ino, u32 gen)) | ||
719 | { | ||
720 | struct inode *inode = NULL; | ||
721 | |||
722 | if (fh_len < 2) | ||
723 | return NULL; | ||
724 | |||
725 | switch (fh_type) { | ||
726 | case FILEID_INO32_GEN: | ||
727 | case FILEID_INO32_GEN_PARENT: | ||
728 | inode = get_inode(sb, fid->i32.ino, fid->i32.gen); | ||
729 | break; | ||
730 | } | ||
731 | |||
732 | return exportfs_d_alloc(inode); | ||
733 | } | ||
734 | EXPORT_SYMBOL_GPL(generic_fh_to_dentry); | ||
735 | |||
736 | /** | ||
737 | * generic_fh_to_dentry - generic helper for the fh_to_parent export operation | ||
738 | * @sb: filesystem to do the file handle conversion on | ||
739 | * @fid: file handle to convert | ||
740 | * @fh_len: length of the file handle in bytes | ||
741 | * @fh_type: type of file handle | ||
742 | * @get_inode: filesystem callback to retrieve inode | ||
743 | * | ||
744 | * This function decodes @fid as long as it has one of the well-known | ||
745 | * Linux filehandle types and calls @get_inode on it to retrieve the | ||
746 | * inode for the _parent_ object specified in the file handle if it | ||
747 | * is specified in the file handle, or NULL otherwise. | ||
748 | */ | ||
749 | struct dentry *generic_fh_to_parent(struct super_block *sb, struct fid *fid, | ||
750 | int fh_len, int fh_type, struct inode *(*get_inode) | ||
751 | (struct super_block *sb, u64 ino, u32 gen)) | ||
752 | { | ||
753 | struct inode *inode = NULL; | ||
754 | |||
755 | if (fh_len <= 2) | ||
756 | return NULL; | ||
757 | |||
758 | switch (fh_type) { | ||
759 | case FILEID_INO32_GEN_PARENT: | ||
760 | inode = get_inode(sb, fid->i32.parent_ino, | ||
761 | (fh_len > 3 ? fid->i32.parent_gen : 0)); | ||
762 | break; | ||
763 | } | ||
764 | |||
765 | return exportfs_d_alloc(inode); | ||
766 | } | ||
767 | EXPORT_SYMBOL_GPL(generic_fh_to_parent); | ||
768 | |||
681 | EXPORT_SYMBOL(dcache_dir_close); | 769 | EXPORT_SYMBOL(dcache_dir_close); |
682 | EXPORT_SYMBOL(dcache_dir_lseek); | 770 | EXPORT_SYMBOL(dcache_dir_lseek); |
683 | EXPORT_SYMBOL(dcache_dir_open); | 771 | EXPORT_SYMBOL(dcache_dir_open); |
diff --git a/fs/locks.c b/fs/locks.c index 0127a2846819..8b8388eca05e 100644 --- a/fs/locks.c +++ b/fs/locks.c | |||
@@ -696,17 +696,28 @@ EXPORT_SYMBOL(posix_test_lock); | |||
696 | * Note: the above assumption may not be true when handling lock requests | 696 | * Note: the above assumption may not be true when handling lock requests |
697 | * from a broken NFS client. But broken NFS clients have a lot more to | 697 | * from a broken NFS client. But broken NFS clients have a lot more to |
698 | * worry about than proper deadlock detection anyway... --okir | 698 | * worry about than proper deadlock detection anyway... --okir |
699 | * | ||
700 | * However, the failure of this assumption (also possible in the case of | ||
701 | * multiple tasks sharing the same open file table) also means there's no | ||
702 | * guarantee that the loop below will terminate. As a hack, we give up | ||
703 | * after a few iterations. | ||
699 | */ | 704 | */ |
705 | |||
706 | #define MAX_DEADLK_ITERATIONS 10 | ||
707 | |||
700 | static int posix_locks_deadlock(struct file_lock *caller_fl, | 708 | static int posix_locks_deadlock(struct file_lock *caller_fl, |
701 | struct file_lock *block_fl) | 709 | struct file_lock *block_fl) |
702 | { | 710 | { |
703 | struct file_lock *fl; | 711 | struct file_lock *fl; |
712 | int i = 0; | ||
704 | 713 | ||
705 | next_task: | 714 | next_task: |
706 | if (posix_same_owner(caller_fl, block_fl)) | 715 | if (posix_same_owner(caller_fl, block_fl)) |
707 | return 1; | 716 | return 1; |
708 | list_for_each_entry(fl, &blocked_list, fl_link) { | 717 | list_for_each_entry(fl, &blocked_list, fl_link) { |
709 | if (posix_same_owner(fl, block_fl)) { | 718 | if (posix_same_owner(fl, block_fl)) { |
719 | if (i++ > MAX_DEADLK_ITERATIONS) | ||
720 | return 0; | ||
710 | fl = fl->fl_next; | 721 | fl = fl->fl_next; |
711 | block_fl = fl; | 722 | block_fl = fl; |
712 | goto next_task; | 723 | goto next_task; |
diff --git a/fs/mbcache.c b/fs/mbcache.c index 1046cbefbfbf..eb31b73e7d69 100644 --- a/fs/mbcache.c +++ b/fs/mbcache.c | |||
@@ -403,9 +403,9 @@ mb_cache_entry_alloc(struct mb_cache *cache) | |||
403 | { | 403 | { |
404 | struct mb_cache_entry *ce; | 404 | struct mb_cache_entry *ce; |
405 | 405 | ||
406 | atomic_inc(&cache->c_entry_count); | ||
407 | ce = kmem_cache_alloc(cache->c_entry_cache, GFP_KERNEL); | 406 | ce = kmem_cache_alloc(cache->c_entry_cache, GFP_KERNEL); |
408 | if (ce) { | 407 | if (ce) { |
408 | atomic_inc(&cache->c_entry_count); | ||
409 | INIT_LIST_HEAD(&ce->e_lru_list); | 409 | INIT_LIST_HEAD(&ce->e_lru_list); |
410 | INIT_LIST_HEAD(&ce->e_block_list); | 410 | INIT_LIST_HEAD(&ce->e_block_list); |
411 | ce->e_cache = cache; | 411 | ce->e_cache = cache; |
diff --git a/fs/namei.c b/fs/namei.c index 1e5c71669164..3b993db26cee 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -1174,7 +1174,7 @@ static int fastcall do_path_lookup(int dfd, const char *name, | |||
1174 | out: | 1174 | out: |
1175 | if (unlikely(!retval && !audit_dummy_context() && nd->dentry && | 1175 | if (unlikely(!retval && !audit_dummy_context() && nd->dentry && |
1176 | nd->dentry->d_inode)) | 1176 | nd->dentry->d_inode)) |
1177 | audit_inode(name, nd->dentry->d_inode); | 1177 | audit_inode(name, nd->dentry); |
1178 | out_fail: | 1178 | out_fail: |
1179 | return retval; | 1179 | return retval; |
1180 | 1180 | ||
@@ -1214,7 +1214,7 @@ int vfs_path_lookup(struct dentry *dentry, struct vfsmount *mnt, | |||
1214 | retval = path_walk(name, nd); | 1214 | retval = path_walk(name, nd); |
1215 | if (unlikely(!retval && !audit_dummy_context() && nd->dentry && | 1215 | if (unlikely(!retval && !audit_dummy_context() && nd->dentry && |
1216 | nd->dentry->d_inode)) | 1216 | nd->dentry->d_inode)) |
1217 | audit_inode(name, nd->dentry->d_inode); | 1217 | audit_inode(name, nd->dentry); |
1218 | 1218 | ||
1219 | return retval; | 1219 | return retval; |
1220 | 1220 | ||
@@ -1469,7 +1469,7 @@ static int may_delete(struct inode *dir,struct dentry *victim,int isdir) | |||
1469 | return -ENOENT; | 1469 | return -ENOENT; |
1470 | 1470 | ||
1471 | BUG_ON(victim->d_parent->d_inode != dir); | 1471 | BUG_ON(victim->d_parent->d_inode != dir); |
1472 | audit_inode_child(victim->d_name.name, victim->d_inode, dir); | 1472 | audit_inode_child(victim->d_name.name, victim, dir); |
1473 | 1473 | ||
1474 | error = permission(dir,MAY_WRITE | MAY_EXEC, NULL); | 1474 | error = permission(dir,MAY_WRITE | MAY_EXEC, NULL); |
1475 | if (error) | 1475 | if (error) |
@@ -1783,7 +1783,7 @@ do_last: | |||
1783 | * It already exists. | 1783 | * It already exists. |
1784 | */ | 1784 | */ |
1785 | mutex_unlock(&dir->d_inode->i_mutex); | 1785 | mutex_unlock(&dir->d_inode->i_mutex); |
1786 | audit_inode(pathname, path.dentry->d_inode); | 1786 | audit_inode(pathname, path.dentry); |
1787 | 1787 | ||
1788 | error = -EEXIST; | 1788 | error = -EEXIST; |
1789 | if (flag & O_EXCL) | 1789 | if (flag & O_EXCL) |
@@ -2562,7 +2562,7 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
2562 | if (!error) { | 2562 | if (!error) { |
2563 | const char *new_name = old_dentry->d_name.name; | 2563 | const char *new_name = old_dentry->d_name.name; |
2564 | fsnotify_move(old_dir, new_dir, old_name, new_name, is_dir, | 2564 | fsnotify_move(old_dir, new_dir, old_name, new_name, is_dir, |
2565 | new_dentry->d_inode, old_dentry->d_inode); | 2565 | new_dentry->d_inode, old_dentry); |
2566 | } | 2566 | } |
2567 | fsnotify_oldname_free(old_name); | 2567 | fsnotify_oldname_free(old_name); |
2568 | 2568 | ||
diff --git a/fs/namespace.c b/fs/namespace.c index 07daa7972591..06083885b21e 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
@@ -246,7 +246,7 @@ static struct vfsmount *clone_mnt(struct vfsmount *old, struct dentry *root, | |||
246 | list_add(&mnt->mnt_slave, &old->mnt_slave_list); | 246 | list_add(&mnt->mnt_slave, &old->mnt_slave_list); |
247 | mnt->mnt_master = old; | 247 | mnt->mnt_master = old; |
248 | CLEAR_MNT_SHARED(mnt); | 248 | CLEAR_MNT_SHARED(mnt); |
249 | } else { | 249 | } else if (!(flag & CL_PRIVATE)) { |
250 | if ((flag & CL_PROPAGATION) || IS_MNT_SHARED(old)) | 250 | if ((flag & CL_PROPAGATION) || IS_MNT_SHARED(old)) |
251 | list_add(&mnt->mnt_share, &old->mnt_share); | 251 | list_add(&mnt->mnt_share, &old->mnt_share); |
252 | if (IS_MNT_SLAVE(old)) | 252 | if (IS_MNT_SLAVE(old)) |
@@ -746,6 +746,26 @@ Enomem: | |||
746 | return NULL; | 746 | return NULL; |
747 | } | 747 | } |
748 | 748 | ||
749 | struct vfsmount *collect_mounts(struct vfsmount *mnt, struct dentry *dentry) | ||
750 | { | ||
751 | struct vfsmount *tree; | ||
752 | down_read(&namespace_sem); | ||
753 | tree = copy_tree(mnt, dentry, CL_COPY_ALL | CL_PRIVATE); | ||
754 | up_read(&namespace_sem); | ||
755 | return tree; | ||
756 | } | ||
757 | |||
758 | void drop_collected_mounts(struct vfsmount *mnt) | ||
759 | { | ||
760 | LIST_HEAD(umount_list); | ||
761 | down_read(&namespace_sem); | ||
762 | spin_lock(&vfsmount_lock); | ||
763 | umount_tree(mnt, 0, &umount_list); | ||
764 | spin_unlock(&vfsmount_lock); | ||
765 | up_read(&namespace_sem); | ||
766 | release_mounts(&umount_list); | ||
767 | } | ||
768 | |||
749 | /* | 769 | /* |
750 | * @source_mnt : mount tree to be attached | 770 | * @source_mnt : mount tree to be attached |
751 | * @nd : place the mount tree @source_mnt is attached | 771 | * @nd : place the mount tree @source_mnt is attached |
@@ -1411,7 +1431,7 @@ long do_mount(char *dev_name, char *dir_name, char *type_page, | |||
1411 | mnt_flags |= MNT_RELATIME; | 1431 | mnt_flags |= MNT_RELATIME; |
1412 | 1432 | ||
1413 | flags &= ~(MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_ACTIVE | | 1433 | flags &= ~(MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_ACTIVE | |
1414 | MS_NOATIME | MS_NODIRATIME | MS_RELATIME); | 1434 | MS_NOATIME | MS_NODIRATIME | MS_RELATIME| MS_KERNMOUNT); |
1415 | 1435 | ||
1416 | /* ... and get the mountpoint */ | 1436 | /* ... and get the mountpoint */ |
1417 | retval = path_lookup(dir_name, LOOKUP_FOLLOW, &nd); | 1437 | retval = path_lookup(dir_name, LOOKUP_FOLLOW, &nd); |
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c index af8b235d405d..11833f4caeaa 100644 --- a/fs/nfs/delegation.c +++ b/fs/nfs/delegation.c | |||
@@ -168,7 +168,8 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct | |||
168 | spin_unlock(&inode->i_lock); | 168 | spin_unlock(&inode->i_lock); |
169 | 169 | ||
170 | spin_unlock(&clp->cl_lock); | 170 | spin_unlock(&clp->cl_lock); |
171 | kfree(delegation); | 171 | if (delegation != NULL) |
172 | nfs_free_delegation(delegation); | ||
172 | return status; | 173 | return status; |
173 | } | 174 | } |
174 | 175 | ||
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 8ec7fbd8240c..f697b5c74b7c 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include "nfs4_fs.h" | 38 | #include "nfs4_fs.h" |
39 | #include "delegation.h" | 39 | #include "delegation.h" |
40 | #include "iostat.h" | 40 | #include "iostat.h" |
41 | #include "internal.h" | ||
41 | 42 | ||
42 | /* #define NFS_DEBUG_VERBOSE 1 */ | 43 | /* #define NFS_DEBUG_VERBOSE 1 */ |
43 | 44 | ||
@@ -562,6 +563,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
562 | nfs_fattr_init(&fattr); | 563 | nfs_fattr_init(&fattr); |
563 | desc->entry = &my_entry; | 564 | desc->entry = &my_entry; |
564 | 565 | ||
566 | nfs_block_sillyrename(dentry); | ||
565 | while(!desc->entry->eof) { | 567 | while(!desc->entry->eof) { |
566 | res = readdir_search_pagecache(desc); | 568 | res = readdir_search_pagecache(desc); |
567 | 569 | ||
@@ -592,6 +594,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
592 | break; | 594 | break; |
593 | } | 595 | } |
594 | } | 596 | } |
597 | nfs_unblock_sillyrename(dentry); | ||
595 | unlock_kernel(); | 598 | unlock_kernel(); |
596 | if (res > 0) | 599 | if (res > 0) |
597 | res = 0; | 600 | res = 0; |
@@ -866,6 +869,7 @@ struct dentry_operations nfs_dentry_operations = { | |||
866 | static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd) | 869 | static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd) |
867 | { | 870 | { |
868 | struct dentry *res; | 871 | struct dentry *res; |
872 | struct dentry *parent; | ||
869 | struct inode *inode = NULL; | 873 | struct inode *inode = NULL; |
870 | int error; | 874 | int error; |
871 | struct nfs_fh fhandle; | 875 | struct nfs_fh fhandle; |
@@ -894,26 +898,31 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru | |||
894 | goto out_unlock; | 898 | goto out_unlock; |
895 | } | 899 | } |
896 | 900 | ||
901 | parent = dentry->d_parent; | ||
902 | /* Protect against concurrent sillydeletes */ | ||
903 | nfs_block_sillyrename(parent); | ||
897 | error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr); | 904 | error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr); |
898 | if (error == -ENOENT) | 905 | if (error == -ENOENT) |
899 | goto no_entry; | 906 | goto no_entry; |
900 | if (error < 0) { | 907 | if (error < 0) { |
901 | res = ERR_PTR(error); | 908 | res = ERR_PTR(error); |
902 | goto out_unlock; | 909 | goto out_unblock_sillyrename; |
903 | } | 910 | } |
904 | inode = nfs_fhget(dentry->d_sb, &fhandle, &fattr); | 911 | inode = nfs_fhget(dentry->d_sb, &fhandle, &fattr); |
905 | res = (struct dentry *)inode; | 912 | res = (struct dentry *)inode; |
906 | if (IS_ERR(res)) | 913 | if (IS_ERR(res)) |
907 | goto out_unlock; | 914 | goto out_unblock_sillyrename; |
908 | 915 | ||
909 | no_entry: | 916 | no_entry: |
910 | res = d_materialise_unique(dentry, inode); | 917 | res = d_materialise_unique(dentry, inode); |
911 | if (res != NULL) { | 918 | if (res != NULL) { |
912 | if (IS_ERR(res)) | 919 | if (IS_ERR(res)) |
913 | goto out_unlock; | 920 | goto out_unblock_sillyrename; |
914 | dentry = res; | 921 | dentry = res; |
915 | } | 922 | } |
916 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | 923 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); |
924 | out_unblock_sillyrename: | ||
925 | nfs_unblock_sillyrename(parent); | ||
917 | out_unlock: | 926 | out_unlock: |
918 | unlock_kernel(); | 927 | unlock_kernel(); |
919 | out: | 928 | out: |
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index 32fe97211eea..5e8d82f6666b 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c | |||
@@ -263,17 +263,19 @@ static const struct rpc_call_ops nfs_read_direct_ops = { | |||
263 | * handled automatically by nfs_direct_read_result(). Otherwise, if | 263 | * handled automatically by nfs_direct_read_result(). Otherwise, if |
264 | * no requests have been sent, just return an error. | 264 | * no requests have been sent, just return an error. |
265 | */ | 265 | */ |
266 | static ssize_t nfs_direct_read_schedule(struct nfs_direct_req *dreq, unsigned long user_addr, size_t count, loff_t pos) | 266 | static ssize_t nfs_direct_read_schedule_segment(struct nfs_direct_req *dreq, |
267 | const struct iovec *iov, | ||
268 | loff_t pos) | ||
267 | { | 269 | { |
268 | struct nfs_open_context *ctx = dreq->ctx; | 270 | struct nfs_open_context *ctx = dreq->ctx; |
269 | struct inode *inode = ctx->path.dentry->d_inode; | 271 | struct inode *inode = ctx->path.dentry->d_inode; |
272 | unsigned long user_addr = (unsigned long)iov->iov_base; | ||
273 | size_t count = iov->iov_len; | ||
270 | size_t rsize = NFS_SERVER(inode)->rsize; | 274 | size_t rsize = NFS_SERVER(inode)->rsize; |
271 | unsigned int pgbase; | 275 | unsigned int pgbase; |
272 | int result; | 276 | int result; |
273 | ssize_t started = 0; | 277 | ssize_t started = 0; |
274 | 278 | ||
275 | get_dreq(dreq); | ||
276 | |||
277 | do { | 279 | do { |
278 | struct nfs_read_data *data; | 280 | struct nfs_read_data *data; |
279 | size_t bytes; | 281 | size_t bytes; |
@@ -347,15 +349,46 @@ static ssize_t nfs_direct_read_schedule(struct nfs_direct_req *dreq, unsigned lo | |||
347 | count -= bytes; | 349 | count -= bytes; |
348 | } while (count != 0); | 350 | } while (count != 0); |
349 | 351 | ||
352 | if (started) | ||
353 | return started; | ||
354 | return result < 0 ? (ssize_t) result : -EFAULT; | ||
355 | } | ||
356 | |||
357 | static ssize_t nfs_direct_read_schedule_iovec(struct nfs_direct_req *dreq, | ||
358 | const struct iovec *iov, | ||
359 | unsigned long nr_segs, | ||
360 | loff_t pos) | ||
361 | { | ||
362 | ssize_t result = -EINVAL; | ||
363 | size_t requested_bytes = 0; | ||
364 | unsigned long seg; | ||
365 | |||
366 | get_dreq(dreq); | ||
367 | |||
368 | for (seg = 0; seg < nr_segs; seg++) { | ||
369 | const struct iovec *vec = &iov[seg]; | ||
370 | result = nfs_direct_read_schedule_segment(dreq, vec, pos); | ||
371 | if (result < 0) | ||
372 | break; | ||
373 | requested_bytes += result; | ||
374 | if ((size_t)result < vec->iov_len) | ||
375 | break; | ||
376 | pos += vec->iov_len; | ||
377 | } | ||
378 | |||
350 | if (put_dreq(dreq)) | 379 | if (put_dreq(dreq)) |
351 | nfs_direct_complete(dreq); | 380 | nfs_direct_complete(dreq); |
352 | 381 | ||
353 | if (started) | 382 | if (requested_bytes != 0) |
354 | return 0; | 383 | return 0; |
355 | return result < 0 ? (ssize_t) result : -EFAULT; | 384 | |
385 | if (result < 0) | ||
386 | return result; | ||
387 | return -EIO; | ||
356 | } | 388 | } |
357 | 389 | ||
358 | static ssize_t nfs_direct_read(struct kiocb *iocb, unsigned long user_addr, size_t count, loff_t pos) | 390 | static ssize_t nfs_direct_read(struct kiocb *iocb, const struct iovec *iov, |
391 | unsigned long nr_segs, loff_t pos) | ||
359 | { | 392 | { |
360 | ssize_t result = 0; | 393 | ssize_t result = 0; |
361 | sigset_t oldset; | 394 | sigset_t oldset; |
@@ -372,9 +405,8 @@ static ssize_t nfs_direct_read(struct kiocb *iocb, unsigned long user_addr, size | |||
372 | if (!is_sync_kiocb(iocb)) | 405 | if (!is_sync_kiocb(iocb)) |
373 | dreq->iocb = iocb; | 406 | dreq->iocb = iocb; |
374 | 407 | ||
375 | nfs_add_stats(inode, NFSIOS_DIRECTREADBYTES, count); | ||
376 | rpc_clnt_sigmask(clnt, &oldset); | 408 | rpc_clnt_sigmask(clnt, &oldset); |
377 | result = nfs_direct_read_schedule(dreq, user_addr, count, pos); | 409 | result = nfs_direct_read_schedule_iovec(dreq, iov, nr_segs, pos); |
378 | if (!result) | 410 | if (!result) |
379 | result = nfs_direct_wait(dreq); | 411 | result = nfs_direct_wait(dreq); |
380 | rpc_clnt_sigunmask(clnt, &oldset); | 412 | rpc_clnt_sigunmask(clnt, &oldset); |
@@ -549,13 +581,13 @@ static void nfs_direct_write_result(struct rpc_task *task, void *calldata) | |||
549 | 581 | ||
550 | spin_lock(&dreq->lock); | 582 | spin_lock(&dreq->lock); |
551 | 583 | ||
552 | if (unlikely(dreq->error != 0)) | ||
553 | goto out_unlock; | ||
554 | if (unlikely(status < 0)) { | 584 | if (unlikely(status < 0)) { |
555 | /* An error has occured, so we should not commit */ | 585 | /* An error has occurred, so we should not commit */ |
556 | dreq->flags = 0; | 586 | dreq->flags = 0; |
557 | dreq->error = status; | 587 | dreq->error = status; |
558 | } | 588 | } |
589 | if (unlikely(dreq->error != 0)) | ||
590 | goto out_unlock; | ||
559 | 591 | ||
560 | dreq->count += data->res.count; | 592 | dreq->count += data->res.count; |
561 | 593 | ||
@@ -601,17 +633,19 @@ static const struct rpc_call_ops nfs_write_direct_ops = { | |||
601 | * handled automatically by nfs_direct_write_result(). Otherwise, if | 633 | * handled automatically by nfs_direct_write_result(). Otherwise, if |
602 | * no requests have been sent, just return an error. | 634 | * no requests have been sent, just return an error. |
603 | */ | 635 | */ |
604 | static ssize_t nfs_direct_write_schedule(struct nfs_direct_req *dreq, unsigned long user_addr, size_t count, loff_t pos, int sync) | 636 | static ssize_t nfs_direct_write_schedule_segment(struct nfs_direct_req *dreq, |
637 | const struct iovec *iov, | ||
638 | loff_t pos, int sync) | ||
605 | { | 639 | { |
606 | struct nfs_open_context *ctx = dreq->ctx; | 640 | struct nfs_open_context *ctx = dreq->ctx; |
607 | struct inode *inode = ctx->path.dentry->d_inode; | 641 | struct inode *inode = ctx->path.dentry->d_inode; |
642 | unsigned long user_addr = (unsigned long)iov->iov_base; | ||
643 | size_t count = iov->iov_len; | ||
608 | size_t wsize = NFS_SERVER(inode)->wsize; | 644 | size_t wsize = NFS_SERVER(inode)->wsize; |
609 | unsigned int pgbase; | 645 | unsigned int pgbase; |
610 | int result; | 646 | int result; |
611 | ssize_t started = 0; | 647 | ssize_t started = 0; |
612 | 648 | ||
613 | get_dreq(dreq); | ||
614 | |||
615 | do { | 649 | do { |
616 | struct nfs_write_data *data; | 650 | struct nfs_write_data *data; |
617 | size_t bytes; | 651 | size_t bytes; |
@@ -689,15 +723,48 @@ static ssize_t nfs_direct_write_schedule(struct nfs_direct_req *dreq, unsigned l | |||
689 | count -= bytes; | 723 | count -= bytes; |
690 | } while (count != 0); | 724 | } while (count != 0); |
691 | 725 | ||
726 | if (started) | ||
727 | return started; | ||
728 | return result < 0 ? (ssize_t) result : -EFAULT; | ||
729 | } | ||
730 | |||
731 | static ssize_t nfs_direct_write_schedule_iovec(struct nfs_direct_req *dreq, | ||
732 | const struct iovec *iov, | ||
733 | unsigned long nr_segs, | ||
734 | loff_t pos, int sync) | ||
735 | { | ||
736 | ssize_t result = 0; | ||
737 | size_t requested_bytes = 0; | ||
738 | unsigned long seg; | ||
739 | |||
740 | get_dreq(dreq); | ||
741 | |||
742 | for (seg = 0; seg < nr_segs; seg++) { | ||
743 | const struct iovec *vec = &iov[seg]; | ||
744 | result = nfs_direct_write_schedule_segment(dreq, vec, | ||
745 | pos, sync); | ||
746 | if (result < 0) | ||
747 | break; | ||
748 | requested_bytes += result; | ||
749 | if ((size_t)result < vec->iov_len) | ||
750 | break; | ||
751 | pos += vec->iov_len; | ||
752 | } | ||
753 | |||
692 | if (put_dreq(dreq)) | 754 | if (put_dreq(dreq)) |
693 | nfs_direct_write_complete(dreq, inode); | 755 | nfs_direct_write_complete(dreq, dreq->inode); |
694 | 756 | ||
695 | if (started) | 757 | if (requested_bytes != 0) |
696 | return 0; | 758 | return 0; |
697 | return result < 0 ? (ssize_t) result : -EFAULT; | 759 | |
760 | if (result < 0) | ||
761 | return result; | ||
762 | return -EIO; | ||
698 | } | 763 | } |
699 | 764 | ||
700 | static ssize_t nfs_direct_write(struct kiocb *iocb, unsigned long user_addr, size_t count, loff_t pos) | 765 | static ssize_t nfs_direct_write(struct kiocb *iocb, const struct iovec *iov, |
766 | unsigned long nr_segs, loff_t pos, | ||
767 | size_t count) | ||
701 | { | 768 | { |
702 | ssize_t result = 0; | 769 | ssize_t result = 0; |
703 | sigset_t oldset; | 770 | sigset_t oldset; |
@@ -720,10 +787,8 @@ static ssize_t nfs_direct_write(struct kiocb *iocb, unsigned long user_addr, siz | |||
720 | if (!is_sync_kiocb(iocb)) | 787 | if (!is_sync_kiocb(iocb)) |
721 | dreq->iocb = iocb; | 788 | dreq->iocb = iocb; |
722 | 789 | ||
723 | nfs_add_stats(inode, NFSIOS_DIRECTWRITTENBYTES, count); | ||
724 | |||
725 | rpc_clnt_sigmask(clnt, &oldset); | 790 | rpc_clnt_sigmask(clnt, &oldset); |
726 | result = nfs_direct_write_schedule(dreq, user_addr, count, pos, sync); | 791 | result = nfs_direct_write_schedule_iovec(dreq, iov, nr_segs, pos, sync); |
727 | if (!result) | 792 | if (!result) |
728 | result = nfs_direct_wait(dreq); | 793 | result = nfs_direct_wait(dreq); |
729 | rpc_clnt_sigunmask(clnt, &oldset); | 794 | rpc_clnt_sigunmask(clnt, &oldset); |
@@ -759,21 +824,16 @@ ssize_t nfs_file_direct_read(struct kiocb *iocb, const struct iovec *iov, | |||
759 | ssize_t retval = -EINVAL; | 824 | ssize_t retval = -EINVAL; |
760 | struct file *file = iocb->ki_filp; | 825 | struct file *file = iocb->ki_filp; |
761 | struct address_space *mapping = file->f_mapping; | 826 | struct address_space *mapping = file->f_mapping; |
762 | /* XXX: temporary */ | 827 | size_t count; |
763 | const char __user *buf = iov[0].iov_base; | 828 | |
764 | size_t count = iov[0].iov_len; | 829 | count = iov_length(iov, nr_segs); |
830 | nfs_add_stats(mapping->host, NFSIOS_DIRECTREADBYTES, count); | ||
765 | 831 | ||
766 | dprintk("nfs: direct read(%s/%s, %lu@%Ld)\n", | 832 | dprintk("nfs: direct read(%s/%s, %zd@%Ld)\n", |
767 | file->f_path.dentry->d_parent->d_name.name, | 833 | file->f_path.dentry->d_parent->d_name.name, |
768 | file->f_path.dentry->d_name.name, | 834 | file->f_path.dentry->d_name.name, |
769 | (unsigned long) count, (long long) pos); | 835 | count, (long long) pos); |
770 | 836 | ||
771 | if (nr_segs != 1) | ||
772 | goto out; | ||
773 | |||
774 | retval = -EFAULT; | ||
775 | if (!access_ok(VERIFY_WRITE, buf, count)) | ||
776 | goto out; | ||
777 | retval = 0; | 837 | retval = 0; |
778 | if (!count) | 838 | if (!count) |
779 | goto out; | 839 | goto out; |
@@ -782,7 +842,7 @@ ssize_t nfs_file_direct_read(struct kiocb *iocb, const struct iovec *iov, | |||
782 | if (retval) | 842 | if (retval) |
783 | goto out; | 843 | goto out; |
784 | 844 | ||
785 | retval = nfs_direct_read(iocb, (unsigned long) buf, count, pos); | 845 | retval = nfs_direct_read(iocb, iov, nr_segs, pos); |
786 | if (retval > 0) | 846 | if (retval > 0) |
787 | iocb->ki_pos = pos + retval; | 847 | iocb->ki_pos = pos + retval; |
788 | 848 | ||
@@ -821,21 +881,21 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, const struct iovec *iov, | |||
821 | ssize_t retval = -EINVAL; | 881 | ssize_t retval = -EINVAL; |
822 | struct file *file = iocb->ki_filp; | 882 | struct file *file = iocb->ki_filp; |
823 | struct address_space *mapping = file->f_mapping; | 883 | struct address_space *mapping = file->f_mapping; |
824 | /* XXX: temporary */ | 884 | size_t count; |
825 | const char __user *buf = iov[0].iov_base; | ||
826 | size_t count = iov[0].iov_len; | ||
827 | 885 | ||
828 | dprintk("nfs: direct write(%s/%s, %lu@%Ld)\n", | 886 | count = iov_length(iov, nr_segs); |
887 | nfs_add_stats(mapping->host, NFSIOS_DIRECTWRITTENBYTES, count); | ||
888 | |||
889 | dfprintk(VFS, "nfs: direct write(%s/%s, %zd@%Ld)\n", | ||
829 | file->f_path.dentry->d_parent->d_name.name, | 890 | file->f_path.dentry->d_parent->d_name.name, |
830 | file->f_path.dentry->d_name.name, | 891 | file->f_path.dentry->d_name.name, |
831 | (unsigned long) count, (long long) pos); | 892 | count, (long long) pos); |
832 | |||
833 | if (nr_segs != 1) | ||
834 | goto out; | ||
835 | 893 | ||
836 | retval = generic_write_checks(file, &pos, &count, 0); | 894 | retval = generic_write_checks(file, &pos, &count, 0); |
837 | if (retval) | 895 | if (retval) |
838 | goto out; | 896 | goto out; |
897 | if (!count) | ||
898 | goto out; /* return 0 */ | ||
839 | 899 | ||
840 | retval = -EINVAL; | 900 | retval = -EINVAL; |
841 | if ((ssize_t) count < 0) | 901 | if ((ssize_t) count < 0) |
@@ -844,15 +904,11 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, const struct iovec *iov, | |||
844 | if (!count) | 904 | if (!count) |
845 | goto out; | 905 | goto out; |
846 | 906 | ||
847 | retval = -EFAULT; | ||
848 | if (!access_ok(VERIFY_READ, buf, count)) | ||
849 | goto out; | ||
850 | |||
851 | retval = nfs_sync_mapping(mapping); | 907 | retval = nfs_sync_mapping(mapping); |
852 | if (retval) | 908 | if (retval) |
853 | goto out; | 909 | goto out; |
854 | 910 | ||
855 | retval = nfs_direct_write(iocb, (unsigned long) buf, count, pos); | 911 | retval = nfs_direct_write(iocb, iov, nr_segs, pos, count); |
856 | 912 | ||
857 | if (retval > 0) | 913 | if (retval > 0) |
858 | iocb->ki_pos = pos + retval; | 914 | iocb->ki_pos = pos + retval; |
diff --git a/fs/nfs/file.c b/fs/nfs/file.c index d29f90d00aa2..b3bb89f7d5d2 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c | |||
@@ -131,7 +131,7 @@ nfs_file_release(struct inode *inode, struct file *filp) | |||
131 | { | 131 | { |
132 | /* Ensure that dirty pages are flushed out with the right creds */ | 132 | /* Ensure that dirty pages are flushed out with the right creds */ |
133 | if (filp->f_mode & FMODE_WRITE) | 133 | if (filp->f_mode & FMODE_WRITE) |
134 | filemap_fdatawrite(filp->f_mapping); | 134 | nfs_wb_all(filp->f_path.dentry->d_inode); |
135 | nfs_inc_stats(inode, NFSIOS_VFSRELEASE); | 135 | nfs_inc_stats(inode, NFSIOS_VFSRELEASE); |
136 | return NFS_PROTO(inode)->file_release(inode, filp); | 136 | return NFS_PROTO(inode)->file_release(inode, filp); |
137 | } | 137 | } |
diff --git a/fs/nfs/getroot.c b/fs/nfs/getroot.c index 522e5ad4d8ad..0ee43843f4ec 100644 --- a/fs/nfs/getroot.c +++ b/fs/nfs/getroot.c | |||
@@ -43,6 +43,25 @@ | |||
43 | #define NFSDBG_FACILITY NFSDBG_CLIENT | 43 | #define NFSDBG_FACILITY NFSDBG_CLIENT |
44 | 44 | ||
45 | /* | 45 | /* |
46 | * Set the superblock root dentry. | ||
47 | * Note that this function frees the inode in case of error. | ||
48 | */ | ||
49 | static int nfs_superblock_set_dummy_root(struct super_block *sb, struct inode *inode) | ||
50 | { | ||
51 | /* The mntroot acts as the dummy root dentry for this superblock */ | ||
52 | if (sb->s_root == NULL) { | ||
53 | sb->s_root = d_alloc_root(inode); | ||
54 | if (sb->s_root == NULL) { | ||
55 | iput(inode); | ||
56 | return -ENOMEM; | ||
57 | } | ||
58 | /* Circumvent igrab(): we know the inode is not being freed */ | ||
59 | atomic_inc(&inode->i_count); | ||
60 | } | ||
61 | return 0; | ||
62 | } | ||
63 | |||
64 | /* | ||
46 | * get an NFS2/NFS3 root dentry from the root filehandle | 65 | * get an NFS2/NFS3 root dentry from the root filehandle |
47 | */ | 66 | */ |
48 | struct dentry *nfs_get_root(struct super_block *sb, struct nfs_fh *mntfh) | 67 | struct dentry *nfs_get_root(struct super_block *sb, struct nfs_fh *mntfh) |
@@ -54,33 +73,6 @@ struct dentry *nfs_get_root(struct super_block *sb, struct nfs_fh *mntfh) | |||
54 | struct inode *inode; | 73 | struct inode *inode; |
55 | int error; | 74 | int error; |
56 | 75 | ||
57 | /* create a dummy root dentry with dummy inode for this superblock */ | ||
58 | if (!sb->s_root) { | ||
59 | struct nfs_fh dummyfh; | ||
60 | struct dentry *root; | ||
61 | struct inode *iroot; | ||
62 | |||
63 | memset(&dummyfh, 0, sizeof(dummyfh)); | ||
64 | memset(&fattr, 0, sizeof(fattr)); | ||
65 | nfs_fattr_init(&fattr); | ||
66 | fattr.valid = NFS_ATTR_FATTR; | ||
67 | fattr.type = NFDIR; | ||
68 | fattr.mode = S_IFDIR | S_IRUSR | S_IWUSR; | ||
69 | fattr.nlink = 2; | ||
70 | |||
71 | iroot = nfs_fhget(sb, &dummyfh, &fattr); | ||
72 | if (IS_ERR(iroot)) | ||
73 | return ERR_PTR(PTR_ERR(iroot)); | ||
74 | |||
75 | root = d_alloc_root(iroot); | ||
76 | if (!root) { | ||
77 | iput(iroot); | ||
78 | return ERR_PTR(-ENOMEM); | ||
79 | } | ||
80 | |||
81 | sb->s_root = root; | ||
82 | } | ||
83 | |||
84 | /* get the actual root for this mount */ | 76 | /* get the actual root for this mount */ |
85 | fsinfo.fattr = &fattr; | 77 | fsinfo.fattr = &fattr; |
86 | 78 | ||
@@ -96,6 +88,10 @@ struct dentry *nfs_get_root(struct super_block *sb, struct nfs_fh *mntfh) | |||
96 | return ERR_PTR(PTR_ERR(inode)); | 88 | return ERR_PTR(PTR_ERR(inode)); |
97 | } | 89 | } |
98 | 90 | ||
91 | error = nfs_superblock_set_dummy_root(sb, inode); | ||
92 | if (error != 0) | ||
93 | return ERR_PTR(error); | ||
94 | |||
99 | /* root dentries normally start off anonymous and get spliced in later | 95 | /* root dentries normally start off anonymous and get spliced in later |
100 | * if the dentry tree reaches them; however if the dentry already | 96 | * if the dentry tree reaches them; however if the dentry already |
101 | * exists, we'll pick it up at this point and use it as the root | 97 | * exists, we'll pick it up at this point and use it as the root |
@@ -241,33 +237,6 @@ struct dentry *nfs4_get_root(struct super_block *sb, struct nfs_fh *mntfh) | |||
241 | 237 | ||
242 | dprintk("--> nfs4_get_root()\n"); | 238 | dprintk("--> nfs4_get_root()\n"); |
243 | 239 | ||
244 | /* create a dummy root dentry with dummy inode for this superblock */ | ||
245 | if (!sb->s_root) { | ||
246 | struct nfs_fh dummyfh; | ||
247 | struct dentry *root; | ||
248 | struct inode *iroot; | ||
249 | |||
250 | memset(&dummyfh, 0, sizeof(dummyfh)); | ||
251 | memset(&fattr, 0, sizeof(fattr)); | ||
252 | nfs_fattr_init(&fattr); | ||
253 | fattr.valid = NFS_ATTR_FATTR; | ||
254 | fattr.type = NFDIR; | ||
255 | fattr.mode = S_IFDIR | S_IRUSR | S_IWUSR; | ||
256 | fattr.nlink = 2; | ||
257 | |||
258 | iroot = nfs_fhget(sb, &dummyfh, &fattr); | ||
259 | if (IS_ERR(iroot)) | ||
260 | return ERR_PTR(PTR_ERR(iroot)); | ||
261 | |||
262 | root = d_alloc_root(iroot); | ||
263 | if (!root) { | ||
264 | iput(iroot); | ||
265 | return ERR_PTR(-ENOMEM); | ||
266 | } | ||
267 | |||
268 | sb->s_root = root; | ||
269 | } | ||
270 | |||
271 | /* get the info about the server and filesystem */ | 240 | /* get the info about the server and filesystem */ |
272 | error = nfs4_server_capabilities(server, mntfh); | 241 | error = nfs4_server_capabilities(server, mntfh); |
273 | if (error < 0) { | 242 | if (error < 0) { |
@@ -289,6 +258,10 @@ struct dentry *nfs4_get_root(struct super_block *sb, struct nfs_fh *mntfh) | |||
289 | return ERR_PTR(PTR_ERR(inode)); | 258 | return ERR_PTR(PTR_ERR(inode)); |
290 | } | 259 | } |
291 | 260 | ||
261 | error = nfs_superblock_set_dummy_root(sb, inode); | ||
262 | if (error != 0) | ||
263 | return ERR_PTR(error); | ||
264 | |||
292 | /* root dentries normally start off anonymous and get spliced in later | 265 | /* root dentries normally start off anonymous and get spliced in later |
293 | * if the dentry tree reaches them; however if the dentry already | 266 | * if the dentry tree reaches them; however if the dentry already |
294 | * exists, we'll pick it up at this point and use it as the root | 267 | * exists, we'll pick it up at this point and use it as the root |
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 6d2f2a3eccf8..db5d96dc6107 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -514,7 +514,7 @@ struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx) | |||
514 | return ctx; | 514 | return ctx; |
515 | } | 515 | } |
516 | 516 | ||
517 | void put_nfs_open_context(struct nfs_open_context *ctx) | 517 | static void __put_nfs_open_context(struct nfs_open_context *ctx, int wait) |
518 | { | 518 | { |
519 | struct inode *inode = ctx->path.dentry->d_inode; | 519 | struct inode *inode = ctx->path.dentry->d_inode; |
520 | 520 | ||
@@ -522,8 +522,12 @@ void put_nfs_open_context(struct nfs_open_context *ctx) | |||
522 | return; | 522 | return; |
523 | list_del(&ctx->list); | 523 | list_del(&ctx->list); |
524 | spin_unlock(&inode->i_lock); | 524 | spin_unlock(&inode->i_lock); |
525 | if (ctx->state != NULL) | 525 | if (ctx->state != NULL) { |
526 | nfs4_close_state(&ctx->path, ctx->state, ctx->mode); | 526 | if (wait) |
527 | nfs4_close_sync(&ctx->path, ctx->state, ctx->mode); | ||
528 | else | ||
529 | nfs4_close_state(&ctx->path, ctx->state, ctx->mode); | ||
530 | } | ||
527 | if (ctx->cred != NULL) | 531 | if (ctx->cred != NULL) |
528 | put_rpccred(ctx->cred); | 532 | put_rpccred(ctx->cred); |
529 | dput(ctx->path.dentry); | 533 | dput(ctx->path.dentry); |
@@ -531,6 +535,16 @@ void put_nfs_open_context(struct nfs_open_context *ctx) | |||
531 | kfree(ctx); | 535 | kfree(ctx); |
532 | } | 536 | } |
533 | 537 | ||
538 | void put_nfs_open_context(struct nfs_open_context *ctx) | ||
539 | { | ||
540 | __put_nfs_open_context(ctx, 0); | ||
541 | } | ||
542 | |||
543 | static void put_nfs_open_context_sync(struct nfs_open_context *ctx) | ||
544 | { | ||
545 | __put_nfs_open_context(ctx, 1); | ||
546 | } | ||
547 | |||
534 | /* | 548 | /* |
535 | * Ensure that mmap has a recent RPC credential for use when writing out | 549 | * Ensure that mmap has a recent RPC credential for use when writing out |
536 | * shared pages | 550 | * shared pages |
@@ -577,7 +591,7 @@ static void nfs_file_clear_open_context(struct file *filp) | |||
577 | spin_lock(&inode->i_lock); | 591 | spin_lock(&inode->i_lock); |
578 | list_move_tail(&ctx->list, &NFS_I(inode)->open_files); | 592 | list_move_tail(&ctx->list, &NFS_I(inode)->open_files); |
579 | spin_unlock(&inode->i_lock); | 593 | spin_unlock(&inode->i_lock); |
580 | put_nfs_open_context(ctx); | 594 | put_nfs_open_context_sync(ctx); |
581 | } | 595 | } |
582 | } | 596 | } |
583 | 597 | ||
@@ -1169,6 +1183,9 @@ static void init_once(struct kmem_cache * cachep, void *foo) | |||
1169 | INIT_RADIX_TREE(&nfsi->nfs_page_tree, GFP_ATOMIC); | 1183 | INIT_RADIX_TREE(&nfsi->nfs_page_tree, GFP_ATOMIC); |
1170 | nfsi->ncommit = 0; | 1184 | nfsi->ncommit = 0; |
1171 | nfsi->npages = 0; | 1185 | nfsi->npages = 0; |
1186 | atomic_set(&nfsi->silly_count, 1); | ||
1187 | INIT_HLIST_HEAD(&nfsi->silly_list); | ||
1188 | init_waitqueue_head(&nfsi->waitqueue); | ||
1172 | nfs4_init_once(nfsi); | 1189 | nfs4_init_once(nfsi); |
1173 | } | 1190 | } |
1174 | 1191 | ||
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index d2802b1ca3b9..b35069a2aa9e 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h | |||
@@ -178,7 +178,7 @@ extern int nfs4_proc_setclientid(struct nfs_client *, u32, unsigned short, struc | |||
178 | extern int nfs4_proc_setclientid_confirm(struct nfs_client *, struct rpc_cred *); | 178 | extern int nfs4_proc_setclientid_confirm(struct nfs_client *, struct rpc_cred *); |
179 | extern int nfs4_proc_async_renew(struct nfs_client *, struct rpc_cred *); | 179 | extern int nfs4_proc_async_renew(struct nfs_client *, struct rpc_cred *); |
180 | extern int nfs4_proc_renew(struct nfs_client *, struct rpc_cred *); | 180 | extern int nfs4_proc_renew(struct nfs_client *, struct rpc_cred *); |
181 | extern int nfs4_do_close(struct path *path, struct nfs4_state *state); | 181 | extern int nfs4_do_close(struct path *path, struct nfs4_state *state, int wait); |
182 | extern struct dentry *nfs4_atomic_open(struct inode *, struct dentry *, struct nameidata *); | 182 | extern struct dentry *nfs4_atomic_open(struct inode *, struct dentry *, struct nameidata *); |
183 | extern int nfs4_open_revalidate(struct inode *, struct dentry *, int, struct nameidata *); | 183 | extern int nfs4_open_revalidate(struct inode *, struct dentry *, int, struct nameidata *); |
184 | extern int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle); | 184 | extern int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle); |
@@ -209,6 +209,7 @@ extern void nfs4_drop_state_owner(struct nfs4_state_owner *); | |||
209 | extern struct nfs4_state * nfs4_get_open_state(struct inode *, struct nfs4_state_owner *); | 209 | extern struct nfs4_state * nfs4_get_open_state(struct inode *, struct nfs4_state_owner *); |
210 | extern void nfs4_put_open_state(struct nfs4_state *); | 210 | extern void nfs4_put_open_state(struct nfs4_state *); |
211 | extern void nfs4_close_state(struct path *, struct nfs4_state *, mode_t); | 211 | extern void nfs4_close_state(struct path *, struct nfs4_state *, mode_t); |
212 | extern void nfs4_close_sync(struct path *, struct nfs4_state *, mode_t); | ||
212 | extern void nfs4_state_set_mode_locked(struct nfs4_state *, mode_t); | 213 | extern void nfs4_state_set_mode_locked(struct nfs4_state *, mode_t); |
213 | extern void nfs4_schedule_state_recovery(struct nfs_client *); | 214 | extern void nfs4_schedule_state_recovery(struct nfs_client *); |
214 | extern void nfs4_put_lock_state(struct nfs4_lock_state *lsp); | 215 | extern void nfs4_put_lock_state(struct nfs4_lock_state *lsp); |
@@ -235,6 +236,7 @@ extern struct svc_version nfs4_callback_version1; | |||
235 | #else | 236 | #else |
236 | 237 | ||
237 | #define nfs4_close_state(a, b, c) do { } while (0) | 238 | #define nfs4_close_state(a, b, c) do { } while (0) |
239 | #define nfs4_close_sync(a, b, c) do { } while (0) | ||
238 | 240 | ||
239 | #endif /* CONFIG_NFS_V4 */ | 241 | #endif /* CONFIG_NFS_V4 */ |
240 | #endif /* __LINUX_FS_NFS_NFS4_FS.H */ | 242 | #endif /* __LINUX_FS_NFS_NFS4_FS.H */ |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index cb99fd90a9ac..f03d9d5f5ba4 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -1305,7 +1305,7 @@ static const struct rpc_call_ops nfs4_close_ops = { | |||
1305 | * | 1305 | * |
1306 | * NOTE: Caller must be holding the sp->so_owner semaphore! | 1306 | * NOTE: Caller must be holding the sp->so_owner semaphore! |
1307 | */ | 1307 | */ |
1308 | int nfs4_do_close(struct path *path, struct nfs4_state *state) | 1308 | int nfs4_do_close(struct path *path, struct nfs4_state *state, int wait) |
1309 | { | 1309 | { |
1310 | struct nfs_server *server = NFS_SERVER(state->inode); | 1310 | struct nfs_server *server = NFS_SERVER(state->inode); |
1311 | struct nfs4_closedata *calldata; | 1311 | struct nfs4_closedata *calldata; |
@@ -1333,8 +1333,11 @@ int nfs4_do_close(struct path *path, struct nfs4_state *state) | |||
1333 | task = rpc_run_task(server->client, RPC_TASK_ASYNC, &nfs4_close_ops, calldata); | 1333 | task = rpc_run_task(server->client, RPC_TASK_ASYNC, &nfs4_close_ops, calldata); |
1334 | if (IS_ERR(task)) | 1334 | if (IS_ERR(task)) |
1335 | return PTR_ERR(task); | 1335 | return PTR_ERR(task); |
1336 | status = 0; | ||
1337 | if (wait) | ||
1338 | status = rpc_wait_for_completion_task(task); | ||
1336 | rpc_put_task(task); | 1339 | rpc_put_task(task); |
1337 | return 0; | 1340 | return status; |
1338 | out_free_calldata: | 1341 | out_free_calldata: |
1339 | kfree(calldata); | 1342 | kfree(calldata); |
1340 | out: | 1343 | out: |
@@ -1365,13 +1368,14 @@ static int nfs4_intent_set_file(struct nameidata *nd, struct path *path, struct | |||
1365 | } | 1368 | } |
1366 | ret = PTR_ERR(filp); | 1369 | ret = PTR_ERR(filp); |
1367 | out_close: | 1370 | out_close: |
1368 | nfs4_close_state(path, state, nd->intent.open.flags); | 1371 | nfs4_close_sync(path, state, nd->intent.open.flags); |
1369 | return ret; | 1372 | return ret; |
1370 | } | 1373 | } |
1371 | 1374 | ||
1372 | struct dentry * | 1375 | struct dentry * |
1373 | nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd) | 1376 | nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd) |
1374 | { | 1377 | { |
1378 | struct dentry *parent; | ||
1375 | struct path path = { | 1379 | struct path path = { |
1376 | .mnt = nd->mnt, | 1380 | .mnt = nd->mnt, |
1377 | .dentry = dentry, | 1381 | .dentry = dentry, |
@@ -1394,6 +1398,9 @@ nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd) | |||
1394 | cred = rpcauth_lookupcred(NFS_CLIENT(dir)->cl_auth, 0); | 1398 | cred = rpcauth_lookupcred(NFS_CLIENT(dir)->cl_auth, 0); |
1395 | if (IS_ERR(cred)) | 1399 | if (IS_ERR(cred)) |
1396 | return (struct dentry *)cred; | 1400 | return (struct dentry *)cred; |
1401 | parent = dentry->d_parent; | ||
1402 | /* Protect against concurrent sillydeletes */ | ||
1403 | nfs_block_sillyrename(parent); | ||
1397 | state = nfs4_do_open(dir, &path, nd->intent.open.flags, &attr, cred); | 1404 | state = nfs4_do_open(dir, &path, nd->intent.open.flags, &attr, cred); |
1398 | put_rpccred(cred); | 1405 | put_rpccred(cred); |
1399 | if (IS_ERR(state)) { | 1406 | if (IS_ERR(state)) { |
@@ -1401,12 +1408,14 @@ nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd) | |||
1401 | d_add(dentry, NULL); | 1408 | d_add(dentry, NULL); |
1402 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | 1409 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); |
1403 | } | 1410 | } |
1411 | nfs_unblock_sillyrename(parent); | ||
1404 | return (struct dentry *)state; | 1412 | return (struct dentry *)state; |
1405 | } | 1413 | } |
1406 | res = d_add_unique(dentry, igrab(state->inode)); | 1414 | res = d_add_unique(dentry, igrab(state->inode)); |
1407 | if (res != NULL) | 1415 | if (res != NULL) |
1408 | path.dentry = res; | 1416 | path.dentry = res; |
1409 | nfs_set_verifier(path.dentry, nfs_save_change_attribute(dir)); | 1417 | nfs_set_verifier(path.dentry, nfs_save_change_attribute(dir)); |
1418 | nfs_unblock_sillyrename(parent); | ||
1410 | nfs4_intent_set_file(nd, &path, state); | 1419 | nfs4_intent_set_file(nd, &path, state); |
1411 | return res; | 1420 | return res; |
1412 | } | 1421 | } |
@@ -1444,7 +1453,7 @@ nfs4_open_revalidate(struct inode *dir, struct dentry *dentry, int openflags, st | |||
1444 | nfs4_intent_set_file(nd, &path, state); | 1453 | nfs4_intent_set_file(nd, &path, state); |
1445 | return 1; | 1454 | return 1; |
1446 | } | 1455 | } |
1447 | nfs4_close_state(&path, state, openflags); | 1456 | nfs4_close_sync(&path, state, openflags); |
1448 | out_drop: | 1457 | out_drop: |
1449 | d_drop(dentry); | 1458 | d_drop(dentry); |
1450 | return 0; | 1459 | return 0; |
@@ -1898,7 +1907,7 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, | |||
1898 | if (status == 0 && (nd->flags & LOOKUP_OPEN) != 0) | 1907 | if (status == 0 && (nd->flags & LOOKUP_OPEN) != 0) |
1899 | status = nfs4_intent_set_file(nd, &path, state); | 1908 | status = nfs4_intent_set_file(nd, &path, state); |
1900 | else | 1909 | else |
1901 | nfs4_close_state(&path, state, flags); | 1910 | nfs4_close_sync(&path, state, flags); |
1902 | out: | 1911 | out: |
1903 | return status; | 1912 | return status; |
1904 | } | 1913 | } |
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index bfb36261cecb..23a9a36556bf 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c | |||
@@ -425,7 +425,7 @@ void nfs4_put_open_state(struct nfs4_state *state) | |||
425 | /* | 425 | /* |
426 | * Close the current file. | 426 | * Close the current file. |
427 | */ | 427 | */ |
428 | void nfs4_close_state(struct path *path, struct nfs4_state *state, mode_t mode) | 428 | static void __nfs4_close(struct path *path, struct nfs4_state *state, mode_t mode, int wait) |
429 | { | 429 | { |
430 | struct nfs4_state_owner *owner = state->owner; | 430 | struct nfs4_state_owner *owner = state->owner; |
431 | int call_close = 0; | 431 | int call_close = 0; |
@@ -466,7 +466,17 @@ void nfs4_close_state(struct path *path, struct nfs4_state *state, mode_t mode) | |||
466 | nfs4_put_open_state(state); | 466 | nfs4_put_open_state(state); |
467 | nfs4_put_state_owner(owner); | 467 | nfs4_put_state_owner(owner); |
468 | } else | 468 | } else |
469 | nfs4_do_close(path, state); | 469 | nfs4_do_close(path, state, wait); |
470 | } | ||
471 | |||
472 | void nfs4_close_state(struct path *path, struct nfs4_state *state, mode_t mode) | ||
473 | { | ||
474 | __nfs4_close(path, state, mode, 0); | ||
475 | } | ||
476 | |||
477 | void nfs4_close_sync(struct path *path, struct nfs4_state *state, mode_t mode) | ||
478 | { | ||
479 | __nfs4_close(path, state, mode, 1); | ||
470 | } | 480 | } |
471 | 481 | ||
472 | /* | 482 | /* |
diff --git a/fs/nfs/nfsroot.c b/fs/nfs/nfsroot.c index e87b44ee9ac9..4b0334590ee5 100644 --- a/fs/nfs/nfsroot.c +++ b/fs/nfs/nfsroot.c | |||
@@ -43,7 +43,7 @@ | |||
43 | * from being used (thanks to Leo Spiekman) | 43 | * from being used (thanks to Leo Spiekman) |
44 | * Andy Walker : Allow to specify the NFS server in nfs_root | 44 | * Andy Walker : Allow to specify the NFS server in nfs_root |
45 | * without giving a path name | 45 | * without giving a path name |
46 | * Swen Thümmler : Allow to specify the NFS options in nfs_root | 46 | * Swen Thümmler : Allow to specify the NFS options in nfs_root |
47 | * without giving a path name. Fix BOOTP request | 47 | * without giving a path name. Fix BOOTP request |
48 | * for domainname (domainname is NIS domain, not | 48 | * for domainname (domainname is NIS domain, not |
49 | * DNS domain!). Skip dummy devices for BOOTP. | 49 | * DNS domain!). Skip dummy devices for BOOTP. |
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c index 97669ed05500..4f80d88e9fee 100644 --- a/fs/nfs/proc.c +++ b/fs/nfs/proc.c | |||
@@ -211,6 +211,7 @@ nfs_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, | |||
211 | nfs_fattr_init(&fattr); | 211 | nfs_fattr_init(&fattr); |
212 | dprintk("NFS call create %s\n", dentry->d_name.name); | 212 | dprintk("NFS call create %s\n", dentry->d_name.name); |
213 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); | 213 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); |
214 | nfs_mark_for_revalidate(dir); | ||
214 | if (status == 0) | 215 | if (status == 0) |
215 | status = nfs_instantiate(dentry, &fhandle, &fattr); | 216 | status = nfs_instantiate(dentry, &fhandle, &fattr); |
216 | dprintk("NFS reply create: %d\n", status); | 217 | dprintk("NFS reply create: %d\n", status); |
diff --git a/fs/nfs/super.c b/fs/nfs/super.c index fa517ae9207f..2426e713b77f 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c | |||
@@ -1054,10 +1054,11 @@ static int nfs_validate_mount_data(void *options, | |||
1054 | { | 1054 | { |
1055 | struct nfs_mount_data *data = (struct nfs_mount_data *)options; | 1055 | struct nfs_mount_data *data = (struct nfs_mount_data *)options; |
1056 | 1056 | ||
1057 | memset(args, 0, sizeof(*args)); | ||
1058 | |||
1057 | if (data == NULL) | 1059 | if (data == NULL) |
1058 | goto out_no_data; | 1060 | goto out_no_data; |
1059 | 1061 | ||
1060 | memset(args, 0, sizeof(*args)); | ||
1061 | args->flags = (NFS_MOUNT_VER3 | NFS_MOUNT_TCP); | 1062 | args->flags = (NFS_MOUNT_VER3 | NFS_MOUNT_TCP); |
1062 | args->rsize = NFS_MAX_FILE_IO_SIZE; | 1063 | args->rsize = NFS_MAX_FILE_IO_SIZE; |
1063 | args->wsize = NFS_MAX_FILE_IO_SIZE; | 1064 | args->wsize = NFS_MAX_FILE_IO_SIZE; |
@@ -1474,6 +1475,11 @@ static int nfs_xdev_get_sb(struct file_system_type *fs_type, int flags, | |||
1474 | error = PTR_ERR(mntroot); | 1475 | error = PTR_ERR(mntroot); |
1475 | goto error_splat_super; | 1476 | goto error_splat_super; |
1476 | } | 1477 | } |
1478 | if (mntroot->d_inode->i_op != &nfs_dir_inode_operations) { | ||
1479 | dput(mntroot); | ||
1480 | error = -ESTALE; | ||
1481 | goto error_splat_super; | ||
1482 | } | ||
1477 | 1483 | ||
1478 | s->s_flags |= MS_ACTIVE; | 1484 | s->s_flags |= MS_ACTIVE; |
1479 | mnt->mnt_sb = s; | 1485 | mnt->mnt_sb = s; |
@@ -1531,10 +1537,11 @@ static int nfs4_validate_mount_data(void *options, | |||
1531 | struct nfs4_mount_data *data = (struct nfs4_mount_data *)options; | 1537 | struct nfs4_mount_data *data = (struct nfs4_mount_data *)options; |
1532 | char *c; | 1538 | char *c; |
1533 | 1539 | ||
1540 | memset(args, 0, sizeof(*args)); | ||
1541 | |||
1534 | if (data == NULL) | 1542 | if (data == NULL) |
1535 | goto out_no_data; | 1543 | goto out_no_data; |
1536 | 1544 | ||
1537 | memset(args, 0, sizeof(*args)); | ||
1538 | args->rsize = NFS_MAX_FILE_IO_SIZE; | 1545 | args->rsize = NFS_MAX_FILE_IO_SIZE; |
1539 | args->wsize = NFS_MAX_FILE_IO_SIZE; | 1546 | args->wsize = NFS_MAX_FILE_IO_SIZE; |
1540 | args->timeo = 600; | 1547 | args->timeo = 600; |
diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c index 1aed850d18f2..233ad38161f9 100644 --- a/fs/nfs/unlink.c +++ b/fs/nfs/unlink.c | |||
@@ -11,9 +11,11 @@ | |||
11 | #include <linux/sunrpc/sched.h> | 11 | #include <linux/sunrpc/sched.h> |
12 | #include <linux/sunrpc/clnt.h> | 12 | #include <linux/sunrpc/clnt.h> |
13 | #include <linux/nfs_fs.h> | 13 | #include <linux/nfs_fs.h> |
14 | 14 | #include <linux/sched.h> | |
15 | #include <linux/wait.h> | ||
15 | 16 | ||
16 | struct nfs_unlinkdata { | 17 | struct nfs_unlinkdata { |
18 | struct hlist_node list; | ||
17 | struct nfs_removeargs args; | 19 | struct nfs_removeargs args; |
18 | struct nfs_removeres res; | 20 | struct nfs_removeres res; |
19 | struct inode *dir; | 21 | struct inode *dir; |
@@ -52,6 +54,20 @@ static int nfs_copy_dname(struct dentry *dentry, struct nfs_unlinkdata *data) | |||
52 | return 0; | 54 | return 0; |
53 | } | 55 | } |
54 | 56 | ||
57 | static void nfs_free_dname(struct nfs_unlinkdata *data) | ||
58 | { | ||
59 | kfree(data->args.name.name); | ||
60 | data->args.name.name = NULL; | ||
61 | data->args.name.len = 0; | ||
62 | } | ||
63 | |||
64 | static void nfs_dec_sillycount(struct inode *dir) | ||
65 | { | ||
66 | struct nfs_inode *nfsi = NFS_I(dir); | ||
67 | if (atomic_dec_return(&nfsi->silly_count) == 1) | ||
68 | wake_up(&nfsi->waitqueue); | ||
69 | } | ||
70 | |||
55 | /** | 71 | /** |
56 | * nfs_async_unlink_init - Initialize the RPC info | 72 | * nfs_async_unlink_init - Initialize the RPC info |
57 | * task: rpc_task of the sillydelete | 73 | * task: rpc_task of the sillydelete |
@@ -95,6 +111,8 @@ static void nfs_async_unlink_done(struct rpc_task *task, void *calldata) | |||
95 | static void nfs_async_unlink_release(void *calldata) | 111 | static void nfs_async_unlink_release(void *calldata) |
96 | { | 112 | { |
97 | struct nfs_unlinkdata *data = calldata; | 113 | struct nfs_unlinkdata *data = calldata; |
114 | |||
115 | nfs_dec_sillycount(data->dir); | ||
98 | nfs_free_unlinkdata(data); | 116 | nfs_free_unlinkdata(data); |
99 | } | 117 | } |
100 | 118 | ||
@@ -104,33 +122,100 @@ static const struct rpc_call_ops nfs_unlink_ops = { | |||
104 | .rpc_release = nfs_async_unlink_release, | 122 | .rpc_release = nfs_async_unlink_release, |
105 | }; | 123 | }; |
106 | 124 | ||
107 | static int nfs_call_unlink(struct dentry *dentry, struct nfs_unlinkdata *data) | 125 | static int nfs_do_call_unlink(struct dentry *parent, struct inode *dir, struct nfs_unlinkdata *data) |
108 | { | 126 | { |
109 | struct rpc_task *task; | 127 | struct rpc_task *task; |
128 | struct dentry *alias; | ||
129 | |||
130 | alias = d_lookup(parent, &data->args.name); | ||
131 | if (alias != NULL) { | ||
132 | int ret = 0; | ||
133 | /* | ||
134 | * Hey, we raced with lookup... See if we need to transfer | ||
135 | * the sillyrename information to the aliased dentry. | ||
136 | */ | ||
137 | nfs_free_dname(data); | ||
138 | spin_lock(&alias->d_lock); | ||
139 | if (!(alias->d_flags & DCACHE_NFSFS_RENAMED)) { | ||
140 | alias->d_fsdata = data; | ||
141 | alias->d_flags ^= DCACHE_NFSFS_RENAMED; | ||
142 | ret = 1; | ||
143 | } | ||
144 | spin_unlock(&alias->d_lock); | ||
145 | nfs_dec_sillycount(dir); | ||
146 | dput(alias); | ||
147 | return ret; | ||
148 | } | ||
149 | data->dir = igrab(dir); | ||
150 | if (!data->dir) { | ||
151 | nfs_dec_sillycount(dir); | ||
152 | return 0; | ||
153 | } | ||
154 | data->args.fh = NFS_FH(dir); | ||
155 | nfs_fattr_init(&data->res.dir_attr); | ||
156 | |||
157 | task = rpc_run_task(NFS_CLIENT(dir), RPC_TASK_ASYNC, &nfs_unlink_ops, data); | ||
158 | if (!IS_ERR(task)) | ||
159 | rpc_put_task(task); | ||
160 | return 1; | ||
161 | } | ||
162 | |||
163 | static int nfs_call_unlink(struct dentry *dentry, struct nfs_unlinkdata *data) | ||
164 | { | ||
110 | struct dentry *parent; | 165 | struct dentry *parent; |
111 | struct inode *dir; | 166 | struct inode *dir; |
167 | int ret = 0; | ||
112 | 168 | ||
113 | if (nfs_copy_dname(dentry, data) < 0) | ||
114 | goto out_free; | ||
115 | 169 | ||
116 | parent = dget_parent(dentry); | 170 | parent = dget_parent(dentry); |
117 | if (parent == NULL) | 171 | if (parent == NULL) |
118 | goto out_free; | 172 | goto out_free; |
119 | dir = igrab(parent->d_inode); | 173 | dir = parent->d_inode; |
174 | if (nfs_copy_dname(dentry, data) != 0) | ||
175 | goto out_dput; | ||
176 | /* Non-exclusive lock protects against concurrent lookup() calls */ | ||
177 | spin_lock(&dir->i_lock); | ||
178 | if (atomic_inc_not_zero(&NFS_I(dir)->silly_count) == 0) { | ||
179 | /* Deferred delete */ | ||
180 | hlist_add_head(&data->list, &NFS_I(dir)->silly_list); | ||
181 | spin_unlock(&dir->i_lock); | ||
182 | ret = 1; | ||
183 | goto out_dput; | ||
184 | } | ||
185 | spin_unlock(&dir->i_lock); | ||
186 | ret = nfs_do_call_unlink(parent, dir, data); | ||
187 | out_dput: | ||
120 | dput(parent); | 188 | dput(parent); |
121 | if (dir == NULL) | 189 | out_free: |
122 | goto out_free; | 190 | return ret; |
191 | } | ||
123 | 192 | ||
124 | data->dir = dir; | 193 | void nfs_block_sillyrename(struct dentry *dentry) |
125 | data->args.fh = NFS_FH(dir); | 194 | { |
126 | nfs_fattr_init(&data->res.dir_attr); | 195 | struct nfs_inode *nfsi = NFS_I(dentry->d_inode); |
127 | 196 | ||
128 | task = rpc_run_task(NFS_CLIENT(dir), RPC_TASK_ASYNC, &nfs_unlink_ops, data); | 197 | wait_event(nfsi->waitqueue, atomic_cmpxchg(&nfsi->silly_count, 1, 0) == 1); |
129 | if (!IS_ERR(task)) | 198 | } |
130 | rpc_put_task(task); | 199 | |
131 | return 1; | 200 | void nfs_unblock_sillyrename(struct dentry *dentry) |
132 | out_free: | 201 | { |
133 | return 0; | 202 | struct inode *dir = dentry->d_inode; |
203 | struct nfs_inode *nfsi = NFS_I(dir); | ||
204 | struct nfs_unlinkdata *data; | ||
205 | |||
206 | atomic_inc(&nfsi->silly_count); | ||
207 | spin_lock(&dir->i_lock); | ||
208 | while (!hlist_empty(&nfsi->silly_list)) { | ||
209 | if (!atomic_inc_not_zero(&nfsi->silly_count)) | ||
210 | break; | ||
211 | data = hlist_entry(nfsi->silly_list.first, struct nfs_unlinkdata, list); | ||
212 | hlist_del(&data->list); | ||
213 | spin_unlock(&dir->i_lock); | ||
214 | if (nfs_do_call_unlink(dentry, dir, data) == 0) | ||
215 | nfs_free_unlinkdata(data); | ||
216 | spin_lock(&dir->i_lock); | ||
217 | } | ||
218 | spin_unlock(&dir->i_lock); | ||
134 | } | 219 | } |
135 | 220 | ||
136 | /** | 221 | /** |
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 0cf9d1cd9bd2..51cc1bd6a116 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -174,8 +174,6 @@ static void nfs_mark_uptodate(struct page *page, unsigned int base, unsigned int | |||
174 | return; | 174 | return; |
175 | if (count != nfs_page_length(page)) | 175 | if (count != nfs_page_length(page)) |
176 | return; | 176 | return; |
177 | if (count != PAGE_CACHE_SIZE) | ||
178 | zero_user_page(page, count, PAGE_CACHE_SIZE - count, KM_USER0); | ||
179 | SetPageUptodate(page); | 177 | SetPageUptodate(page); |
180 | } | 178 | } |
181 | 179 | ||
@@ -627,7 +625,8 @@ static struct nfs_page * nfs_update_request(struct nfs_open_context* ctx, | |||
627 | return ERR_PTR(error); | 625 | return ERR_PTR(error); |
628 | } | 626 | } |
629 | spin_unlock(&inode->i_lock); | 627 | spin_unlock(&inode->i_lock); |
630 | return new; | 628 | req = new; |
629 | goto zero_page; | ||
631 | } | 630 | } |
632 | spin_unlock(&inode->i_lock); | 631 | spin_unlock(&inode->i_lock); |
633 | 632 | ||
@@ -655,13 +654,23 @@ static struct nfs_page * nfs_update_request(struct nfs_open_context* ctx, | |||
655 | if (offset < req->wb_offset) { | 654 | if (offset < req->wb_offset) { |
656 | req->wb_offset = offset; | 655 | req->wb_offset = offset; |
657 | req->wb_pgbase = offset; | 656 | req->wb_pgbase = offset; |
658 | req->wb_bytes = rqend - req->wb_offset; | 657 | req->wb_bytes = max(end, rqend) - req->wb_offset; |
658 | goto zero_page; | ||
659 | } | 659 | } |
660 | 660 | ||
661 | if (end > rqend) | 661 | if (end > rqend) |
662 | req->wb_bytes = end - req->wb_offset; | 662 | req->wb_bytes = end - req->wb_offset; |
663 | 663 | ||
664 | return req; | 664 | return req; |
665 | zero_page: | ||
666 | /* If this page might potentially be marked as up to date, | ||
667 | * then we need to zero any uninitalised data. */ | ||
668 | if (req->wb_pgbase == 0 && req->wb_bytes != PAGE_CACHE_SIZE | ||
669 | && !PageUptodate(req->wb_page)) | ||
670 | zero_user_page(req->wb_page, req->wb_bytes, | ||
671 | PAGE_CACHE_SIZE - req->wb_bytes, | ||
672 | KM_USER0); | ||
673 | return req; | ||
665 | } | 674 | } |
666 | 675 | ||
667 | int nfs_flush_incompatible(struct file *file, struct page *page) | 676 | int nfs_flush_incompatible(struct file *file, struct page *page) |
@@ -1427,7 +1436,8 @@ out: | |||
1427 | return ret; | 1436 | return ret; |
1428 | } | 1437 | } |
1429 | 1438 | ||
1430 | int nfs_wb_page_priority(struct inode *inode, struct page *page, int how) | 1439 | static int nfs_wb_page_priority(struct inode *inode, struct page *page, |
1440 | int how) | ||
1431 | { | 1441 | { |
1432 | loff_t range_start = page_offset(page); | 1442 | loff_t range_start = page_offset(page); |
1433 | loff_t range_end = range_start + (loff_t)(PAGE_CACHE_SIZE - 1); | 1443 | loff_t range_end = range_start + (loff_t)(PAGE_CACHE_SIZE - 1); |
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c index 04b266729802..66d0aeb32a47 100644 --- a/fs/nfsd/export.c +++ b/fs/nfsd/export.c | |||
@@ -386,15 +386,13 @@ static int check_export(struct inode *inode, int flags, unsigned char *uuid) | |||
386 | dprintk("exp_export: export of non-dev fs without fsid\n"); | 386 | dprintk("exp_export: export of non-dev fs without fsid\n"); |
387 | return -EINVAL; | 387 | return -EINVAL; |
388 | } | 388 | } |
389 | if (!inode->i_sb->s_export_op) { | 389 | |
390 | if (!inode->i_sb->s_export_op || | ||
391 | !inode->i_sb->s_export_op->fh_to_dentry) { | ||
390 | dprintk("exp_export: export of invalid fs type.\n"); | 392 | dprintk("exp_export: export of invalid fs type.\n"); |
391 | return -EINVAL; | 393 | return -EINVAL; |
392 | } | 394 | } |
393 | 395 | ||
394 | /* Ok, we can export it */; | ||
395 | if (!inode->i_sb->s_export_op->find_exported_dentry) | ||
396 | inode->i_sb->s_export_op->find_exported_dentry = | ||
397 | find_exported_dentry; | ||
398 | return 0; | 396 | return 0; |
399 | 397 | ||
400 | } | 398 | } |
diff --git a/fs/nfsd/nfs2acl.c b/fs/nfsd/nfs2acl.c index b61742885011..0e5fa11e6b44 100644 --- a/fs/nfsd/nfs2acl.c +++ b/fs/nfsd/nfs2acl.c | |||
@@ -41,7 +41,7 @@ static __be32 nfsacld_proc_getacl(struct svc_rqst * rqstp, | |||
41 | 41 | ||
42 | fh = fh_copy(&resp->fh, &argp->fh); | 42 | fh = fh_copy(&resp->fh, &argp->fh); |
43 | if ((nfserr = fh_verify(rqstp, &resp->fh, 0, MAY_NOP))) | 43 | if ((nfserr = fh_verify(rqstp, &resp->fh, 0, MAY_NOP))) |
44 | RETURN_STATUS(nfserr_inval); | 44 | RETURN_STATUS(nfserr); |
45 | 45 | ||
46 | if (argp->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT)) | 46 | if (argp->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT)) |
47 | RETURN_STATUS(nfserr_inval); | 47 | RETURN_STATUS(nfserr_inval); |
diff --git a/fs/nfsd/nfs3acl.c b/fs/nfsd/nfs3acl.c index 3e3f2de82c36..b647f2f872dc 100644 --- a/fs/nfsd/nfs3acl.c +++ b/fs/nfsd/nfs3acl.c | |||
@@ -37,7 +37,7 @@ static __be32 nfsd3_proc_getacl(struct svc_rqst * rqstp, | |||
37 | 37 | ||
38 | fh = fh_copy(&resp->fh, &argp->fh); | 38 | fh = fh_copy(&resp->fh, &argp->fh); |
39 | if ((nfserr = fh_verify(rqstp, &resp->fh, 0, MAY_NOP))) | 39 | if ((nfserr = fh_verify(rqstp, &resp->fh, 0, MAY_NOP))) |
40 | RETURN_STATUS(nfserr_inval); | 40 | RETURN_STATUS(nfserr); |
41 | 41 | ||
42 | if (argp->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT)) | 42 | if (argp->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT)) |
43 | RETURN_STATUS(nfserr_inval); | 43 | RETURN_STATUS(nfserr_inval); |
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c index ebd03cc07479..1602cd00dd45 100644 --- a/fs/nfsd/nfs4recover.c +++ b/fs/nfsd/nfs4recover.c | |||
@@ -43,7 +43,7 @@ | |||
43 | #include <linux/file.h> | 43 | #include <linux/file.h> |
44 | #include <linux/namei.h> | 44 | #include <linux/namei.h> |
45 | #include <asm/uaccess.h> | 45 | #include <asm/uaccess.h> |
46 | #include <asm/scatterlist.h> | 46 | #include <linux/scatterlist.h> |
47 | #include <linux/crypto.h> | 47 | #include <linux/crypto.h> |
48 | #include <linux/sched.h> | 48 | #include <linux/sched.h> |
49 | 49 | ||
@@ -88,7 +88,7 @@ nfs4_make_rec_clidname(char *dname, struct xdr_netobj *clname) | |||
88 | { | 88 | { |
89 | struct xdr_netobj cksum; | 89 | struct xdr_netobj cksum; |
90 | struct hash_desc desc; | 90 | struct hash_desc desc; |
91 | struct scatterlist sg[1]; | 91 | struct scatterlist sg; |
92 | __be32 status = nfserr_resource; | 92 | __be32 status = nfserr_resource; |
93 | 93 | ||
94 | dprintk("NFSD: nfs4_make_rec_clidname for %.*s\n", | 94 | dprintk("NFSD: nfs4_make_rec_clidname for %.*s\n", |
@@ -102,11 +102,9 @@ nfs4_make_rec_clidname(char *dname, struct xdr_netobj *clname) | |||
102 | if (cksum.data == NULL) | 102 | if (cksum.data == NULL) |
103 | goto out; | 103 | goto out; |
104 | 104 | ||
105 | sg[0].page = virt_to_page(clname->data); | 105 | sg_init_one(&sg, clname->data, clname->len); |
106 | sg[0].offset = offset_in_page(clname->data); | ||
107 | sg[0].length = clname->len; | ||
108 | 106 | ||
109 | if (crypto_hash_digest(&desc, sg, sg->length, cksum.data)) | 107 | if (crypto_hash_digest(&desc, &sg, sg.length, cksum.data)) |
110 | goto out; | 108 | goto out; |
111 | 109 | ||
112 | md5_to_hex(dname, cksum.data); | 110 | md5_to_hex(dname, cksum.data); |
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c index 7011d62acfc8..468f17a78441 100644 --- a/fs/nfsd/nfsfh.c +++ b/fs/nfsd/nfsfh.c | |||
@@ -95,6 +95,22 @@ nfsd_mode_check(struct svc_rqst *rqstp, umode_t mode, int type) | |||
95 | return 0; | 95 | return 0; |
96 | } | 96 | } |
97 | 97 | ||
98 | static __be32 nfsd_setuser_and_check_port(struct svc_rqst *rqstp, | ||
99 | struct svc_export *exp) | ||
100 | { | ||
101 | /* Check if the request originated from a secure port. */ | ||
102 | if (!rqstp->rq_secure && EX_SECURE(exp)) { | ||
103 | char buf[RPC_MAX_ADDRBUFLEN]; | ||
104 | dprintk(KERN_WARNING | ||
105 | "nfsd: request from insecure port %s!\n", | ||
106 | svc_print_addr(rqstp, buf, sizeof(buf))); | ||
107 | return nfserr_perm; | ||
108 | } | ||
109 | |||
110 | /* Set user creds for this exportpoint */ | ||
111 | return nfserrno(nfsd_setuser(rqstp, exp)); | ||
112 | } | ||
113 | |||
98 | /* | 114 | /* |
99 | * Perform sanity checks on the dentry in a client's file handle. | 115 | * Perform sanity checks on the dentry in a client's file handle. |
100 | * | 116 | * |
@@ -115,8 +131,7 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access) | |||
115 | dprintk("nfsd: fh_verify(%s)\n", SVCFH_fmt(fhp)); | 131 | dprintk("nfsd: fh_verify(%s)\n", SVCFH_fmt(fhp)); |
116 | 132 | ||
117 | if (!fhp->fh_dentry) { | 133 | if (!fhp->fh_dentry) { |
118 | __u32 *datap=NULL; | 134 | struct fid *fid = NULL, sfid; |
119 | __u32 tfh[3]; /* filehandle fragment for oldstyle filehandles */ | ||
120 | int fileid_type; | 135 | int fileid_type; |
121 | int data_left = fh->fh_size/4; | 136 | int data_left = fh->fh_size/4; |
122 | 137 | ||
@@ -128,7 +143,6 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access) | |||
128 | 143 | ||
129 | if (fh->fh_version == 1) { | 144 | if (fh->fh_version == 1) { |
130 | int len; | 145 | int len; |
131 | datap = fh->fh_auth; | ||
132 | if (--data_left<0) goto out; | 146 | if (--data_left<0) goto out; |
133 | switch (fh->fh_auth_type) { | 147 | switch (fh->fh_auth_type) { |
134 | case 0: break; | 148 | case 0: break; |
@@ -144,9 +158,11 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access) | |||
144 | fh->fh_fsid[1] = fh->fh_fsid[2]; | 158 | fh->fh_fsid[1] = fh->fh_fsid[2]; |
145 | } | 159 | } |
146 | if ((data_left -= len)<0) goto out; | 160 | if ((data_left -= len)<0) goto out; |
147 | exp = rqst_exp_find(rqstp, fh->fh_fsid_type, datap); | 161 | exp = rqst_exp_find(rqstp, fh->fh_fsid_type, |
148 | datap += len; | 162 | fh->fh_auth); |
163 | fid = (struct fid *)(fh->fh_auth + len); | ||
149 | } else { | 164 | } else { |
165 | __u32 tfh[2]; | ||
150 | dev_t xdev; | 166 | dev_t xdev; |
151 | ino_t xino; | 167 | ino_t xino; |
152 | if (fh->fh_size != NFS_FHSIZE) | 168 | if (fh->fh_size != NFS_FHSIZE) |
@@ -167,18 +183,7 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access) | |||
167 | goto out; | 183 | goto out; |
168 | } | 184 | } |
169 | 185 | ||
170 | /* Check if the request originated from a secure port. */ | 186 | error = nfsd_setuser_and_check_port(rqstp, exp); |
171 | error = nfserr_perm; | ||
172 | if (!rqstp->rq_secure && EX_SECURE(exp)) { | ||
173 | char buf[RPC_MAX_ADDRBUFLEN]; | ||
174 | printk(KERN_WARNING | ||
175 | "nfsd: request from insecure port %s!\n", | ||
176 | svc_print_addr(rqstp, buf, sizeof(buf))); | ||
177 | goto out; | ||
178 | } | ||
179 | |||
180 | /* Set user creds for this exportpoint */ | ||
181 | error = nfserrno(nfsd_setuser(rqstp, exp)); | ||
182 | if (error) | 187 | if (error) |
183 | goto out; | 188 | goto out; |
184 | 189 | ||
@@ -190,22 +195,22 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access) | |||
190 | error = nfserr_badhandle; | 195 | error = nfserr_badhandle; |
191 | 196 | ||
192 | if (fh->fh_version != 1) { | 197 | if (fh->fh_version != 1) { |
193 | tfh[0] = fh->ofh_ino; | 198 | sfid.i32.ino = fh->ofh_ino; |
194 | tfh[1] = fh->ofh_generation; | 199 | sfid.i32.gen = fh->ofh_generation; |
195 | tfh[2] = fh->ofh_dirino; | 200 | sfid.i32.parent_ino = fh->ofh_dirino; |
196 | datap = tfh; | 201 | fid = &sfid; |
197 | data_left = 3; | 202 | data_left = 3; |
198 | if (fh->ofh_dirino == 0) | 203 | if (fh->ofh_dirino == 0) |
199 | fileid_type = 1; | 204 | fileid_type = FILEID_INO32_GEN; |
200 | else | 205 | else |
201 | fileid_type = 2; | 206 | fileid_type = FILEID_INO32_GEN_PARENT; |
202 | } else | 207 | } else |
203 | fileid_type = fh->fh_fileid_type; | 208 | fileid_type = fh->fh_fileid_type; |
204 | 209 | ||
205 | if (fileid_type == 0) | 210 | if (fileid_type == FILEID_ROOT) |
206 | dentry = dget(exp->ex_dentry); | 211 | dentry = dget(exp->ex_dentry); |
207 | else { | 212 | else { |
208 | dentry = exportfs_decode_fh(exp->ex_mnt, datap, | 213 | dentry = exportfs_decode_fh(exp->ex_mnt, fid, |
209 | data_left, fileid_type, | 214 | data_left, fileid_type, |
210 | nfsd_acceptable, exp); | 215 | nfsd_acceptable, exp); |
211 | } | 216 | } |
@@ -227,18 +232,22 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access) | |||
227 | fhp->fh_export = exp; | 232 | fhp->fh_export = exp; |
228 | nfsd_nr_verified++; | 233 | nfsd_nr_verified++; |
229 | } else { | 234 | } else { |
230 | /* just rechecking permissions | 235 | /* |
231 | * (e.g. nfsproc_create calls fh_verify, then nfsd_create does as well) | 236 | * just rechecking permissions |
237 | * (e.g. nfsproc_create calls fh_verify, then nfsd_create | ||
238 | * does as well) | ||
232 | */ | 239 | */ |
233 | dprintk("nfsd: fh_verify - just checking\n"); | 240 | dprintk("nfsd: fh_verify - just checking\n"); |
234 | dentry = fhp->fh_dentry; | 241 | dentry = fhp->fh_dentry; |
235 | exp = fhp->fh_export; | 242 | exp = fhp->fh_export; |
236 | /* Set user creds for this exportpoint; necessary even | 243 | /* |
244 | * Set user creds for this exportpoint; necessary even | ||
237 | * in the "just checking" case because this may be a | 245 | * in the "just checking" case because this may be a |
238 | * filehandle that was created by fh_compose, and that | 246 | * filehandle that was created by fh_compose, and that |
239 | * is about to be used in another nfsv4 compound | 247 | * is about to be used in another nfsv4 compound |
240 | * operation */ | 248 | * operation. |
241 | error = nfserrno(nfsd_setuser(rqstp, exp)); | 249 | */ |
250 | error = nfsd_setuser_and_check_port(rqstp, exp); | ||
242 | if (error) | 251 | if (error) |
243 | goto out; | 252 | goto out; |
244 | } | 253 | } |
@@ -286,16 +295,21 @@ out: | |||
286 | * an inode. In this case a call to fh_update should be made | 295 | * an inode. In this case a call to fh_update should be made |
287 | * before the fh goes out on the wire ... | 296 | * before the fh goes out on the wire ... |
288 | */ | 297 | */ |
289 | static inline int _fh_update(struct dentry *dentry, struct svc_export *exp, | 298 | static void _fh_update(struct svc_fh *fhp, struct svc_export *exp, |
290 | __u32 *datap, int *maxsize) | 299 | struct dentry *dentry) |
291 | { | 300 | { |
292 | if (dentry == exp->ex_dentry) { | 301 | if (dentry != exp->ex_dentry) { |
293 | *maxsize = 0; | 302 | struct fid *fid = (struct fid *) |
294 | return 0; | 303 | (fhp->fh_handle.fh_auth + fhp->fh_handle.fh_size/4 - 1); |
295 | } | 304 | int maxsize = (fhp->fh_maxsize - fhp->fh_handle.fh_size)/4; |
305 | int subtreecheck = !(exp->ex_flags & NFSEXP_NOSUBTREECHECK); | ||
296 | 306 | ||
297 | return exportfs_encode_fh(dentry, datap, maxsize, | 307 | fhp->fh_handle.fh_fileid_type = |
298 | !(exp->ex_flags & NFSEXP_NOSUBTREECHECK)); | 308 | exportfs_encode_fh(dentry, fid, &maxsize, subtreecheck); |
309 | fhp->fh_handle.fh_size += maxsize * 4; | ||
310 | } else { | ||
311 | fhp->fh_handle.fh_fileid_type = FILEID_ROOT; | ||
312 | } | ||
299 | } | 313 | } |
300 | 314 | ||
301 | /* | 315 | /* |
@@ -457,12 +471,8 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, | |||
457 | datap += len/4; | 471 | datap += len/4; |
458 | fhp->fh_handle.fh_size = 4 + len; | 472 | fhp->fh_handle.fh_size = 4 + len; |
459 | 473 | ||
460 | if (inode) { | 474 | if (inode) |
461 | int size = (fhp->fh_maxsize-len-4)/4; | 475 | _fh_update(fhp, exp, dentry); |
462 | fhp->fh_handle.fh_fileid_type = | ||
463 | _fh_update(dentry, exp, datap, &size); | ||
464 | fhp->fh_handle.fh_size += size*4; | ||
465 | } | ||
466 | if (fhp->fh_handle.fh_fileid_type == 255) | 476 | if (fhp->fh_handle.fh_fileid_type == 255) |
467 | return nfserr_opnotsupp; | 477 | return nfserr_opnotsupp; |
468 | } | 478 | } |
@@ -479,7 +489,6 @@ __be32 | |||
479 | fh_update(struct svc_fh *fhp) | 489 | fh_update(struct svc_fh *fhp) |
480 | { | 490 | { |
481 | struct dentry *dentry; | 491 | struct dentry *dentry; |
482 | __u32 *datap; | ||
483 | 492 | ||
484 | if (!fhp->fh_dentry) | 493 | if (!fhp->fh_dentry) |
485 | goto out_bad; | 494 | goto out_bad; |
@@ -490,15 +499,10 @@ fh_update(struct svc_fh *fhp) | |||
490 | if (fhp->fh_handle.fh_version != 1) { | 499 | if (fhp->fh_handle.fh_version != 1) { |
491 | _fh_update_old(dentry, fhp->fh_export, &fhp->fh_handle); | 500 | _fh_update_old(dentry, fhp->fh_export, &fhp->fh_handle); |
492 | } else { | 501 | } else { |
493 | int size; | 502 | if (fhp->fh_handle.fh_fileid_type != FILEID_ROOT) |
494 | if (fhp->fh_handle.fh_fileid_type != 0) | ||
495 | goto out; | 503 | goto out; |
496 | datap = fhp->fh_handle.fh_auth+ | 504 | |
497 | fhp->fh_handle.fh_size/4 -1; | 505 | _fh_update(fhp, fhp->fh_export, dentry); |
498 | size = (fhp->fh_maxsize - fhp->fh_handle.fh_size)/4; | ||
499 | fhp->fh_handle.fh_fileid_type = | ||
500 | _fh_update(dentry, fhp->fh_export, datap, &size); | ||
501 | fhp->fh_handle.fh_size += size*4; | ||
502 | if (fhp->fh_handle.fh_fileid_type == 255) | 506 | if (fhp->fh_handle.fh_fileid_type == 255) |
503 | return nfserr_opnotsupp; | 507 | return nfserr_opnotsupp; |
504 | } | 508 | } |
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 46934c97f8f7..d0199189924c 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
@@ -1029,13 +1029,13 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, | |||
1029 | if (EX_WGATHER(exp)) { | 1029 | if (EX_WGATHER(exp)) { |
1030 | if (atomic_read(&inode->i_writecount) > 1 | 1030 | if (atomic_read(&inode->i_writecount) > 1 |
1031 | || (last_ino == inode->i_ino && last_dev == inode->i_sb->s_dev)) { | 1031 | || (last_ino == inode->i_ino && last_dev == inode->i_sb->s_dev)) { |
1032 | dprintk("nfsd: write defer %d\n", current->pid); | 1032 | dprintk("nfsd: write defer %d\n", task_pid_nr(current)); |
1033 | msleep(10); | 1033 | msleep(10); |
1034 | dprintk("nfsd: write resume %d\n", current->pid); | 1034 | dprintk("nfsd: write resume %d\n", task_pid_nr(current)); |
1035 | } | 1035 | } |
1036 | 1036 | ||
1037 | if (inode->i_state & I_DIRTY) { | 1037 | if (inode->i_state & I_DIRTY) { |
1038 | dprintk("nfsd: write sync %d\n", current->pid); | 1038 | dprintk("nfsd: write sync %d\n", task_pid_nr(current)); |
1039 | host_err=nfsd_sync(file); | 1039 | host_err=nfsd_sync(file); |
1040 | } | 1040 | } |
1041 | #if 0 | 1041 | #if 0 |
diff --git a/fs/ntfs/ChangeLog b/fs/ntfs/ChangeLog index 345798ebd366..37c11e194372 100644 --- a/fs/ntfs/ChangeLog +++ b/fs/ntfs/ChangeLog | |||
@@ -382,7 +382,7 @@ ToDo/Notes: | |||
382 | own locking so it does not matter if the vfs inode is locked. | 382 | own locking so it does not matter if the vfs inode is locked. |
383 | - Fix bug in mft record writing where we forgot to set the device in | 383 | - Fix bug in mft record writing where we forgot to set the device in |
384 | the buffers when mapping them after the VM had discarded them. | 384 | the buffers when mapping them after the VM had discarded them. |
385 | Thanks to Martin MOKREJÅ for the bug report. | 385 | Thanks to Martin MOKREJÃ… for the bug report. |
386 | 386 | ||
387 | 2.1.22 - Many bug and race fixes and error handling improvements. | 387 | 2.1.22 - Many bug and race fixes and error handling improvements. |
388 | 388 | ||
@@ -1585,7 +1585,7 @@ tng-0.0.4 - Big changes, getting in line with Al Viro's comments. | |||
1585 | for reading $MFT (ntfs_mft_readpage). In the process create dedicated | 1585 | for reading $MFT (ntfs_mft_readpage). In the process create dedicated |
1586 | address space operations (ntfs_mft_aops) for $MFT inode mapping. Also | 1586 | address space operations (ntfs_mft_aops) for $MFT inode mapping. Also |
1587 | removed the now superfluous exports from the kernel core patch. | 1587 | removed the now superfluous exports from the kernel core patch. |
1588 | - Fix a bug where kfree() was used insted of ntfs_free(). | 1588 | - Fix a bug where kfree() was used instead of ntfs_free(). |
1589 | - Change map_mft_record() to take ntfs_inode as argument instead of | 1589 | - Change map_mft_record() to take ntfs_inode as argument instead of |
1590 | vfs inode. Dito for unmap_mft_record(). Adapt all callers. | 1590 | vfs inode. Dito for unmap_mft_record(). Adapt all callers. |
1591 | - Add pointer to ntfs_volume to ntfs_inode. | 1591 | - Add pointer to ntfs_volume to ntfs_inode. |
diff --git a/fs/ntfs/aops.c b/fs/ntfs/aops.c index cfdc7900d271..ad87cb01299b 100644 --- a/fs/ntfs/aops.c +++ b/fs/ntfs/aops.c | |||
@@ -405,6 +405,15 @@ static int ntfs_readpage(struct file *file, struct page *page) | |||
405 | 405 | ||
406 | retry_readpage: | 406 | retry_readpage: |
407 | BUG_ON(!PageLocked(page)); | 407 | BUG_ON(!PageLocked(page)); |
408 | vi = page->mapping->host; | ||
409 | i_size = i_size_read(vi); | ||
410 | /* Is the page fully outside i_size? (truncate in progress) */ | ||
411 | if (unlikely(page->index >= (i_size + PAGE_CACHE_SIZE - 1) >> | ||
412 | PAGE_CACHE_SHIFT)) { | ||
413 | zero_user_page(page, 0, PAGE_CACHE_SIZE, KM_USER0); | ||
414 | ntfs_debug("Read outside i_size - truncated?"); | ||
415 | goto done; | ||
416 | } | ||
408 | /* | 417 | /* |
409 | * This can potentially happen because we clear PageUptodate() during | 418 | * This can potentially happen because we clear PageUptodate() during |
410 | * ntfs_writepage() of MstProtected() attributes. | 419 | * ntfs_writepage() of MstProtected() attributes. |
@@ -413,7 +422,6 @@ retry_readpage: | |||
413 | unlock_page(page); | 422 | unlock_page(page); |
414 | return 0; | 423 | return 0; |
415 | } | 424 | } |
416 | vi = page->mapping->host; | ||
417 | ni = NTFS_I(vi); | 425 | ni = NTFS_I(vi); |
418 | /* | 426 | /* |
419 | * Only $DATA attributes can be encrypted and only unnamed $DATA | 427 | * Only $DATA attributes can be encrypted and only unnamed $DATA |
diff --git a/fs/ntfs/attrib.c b/fs/ntfs/attrib.c index 92dabdcf2b80..50d3b0c258e3 100644 --- a/fs/ntfs/attrib.c +++ b/fs/ntfs/attrib.c | |||
@@ -179,10 +179,7 @@ int ntfs_map_runlist_nolock(ntfs_inode *ni, VCN vcn, ntfs_attr_search_ctx *ctx) | |||
179 | * ntfs_mapping_pairs_decompress() fails. | 179 | * ntfs_mapping_pairs_decompress() fails. |
180 | */ | 180 | */ |
181 | end_vcn = sle64_to_cpu(a->data.non_resident.highest_vcn) + 1; | 181 | end_vcn = sle64_to_cpu(a->data.non_resident.highest_vcn) + 1; |
182 | if (!a->data.non_resident.lowest_vcn && end_vcn == 1) | 182 | if (unlikely(vcn && vcn >= end_vcn)) { |
183 | end_vcn = sle64_to_cpu(a->data.non_resident.allocated_size) >> | ||
184 | ni->vol->cluster_size_bits; | ||
185 | if (unlikely(vcn >= end_vcn)) { | ||
186 | err = -ENOENT; | 183 | err = -ENOENT; |
187 | goto err_out; | 184 | goto err_out; |
188 | } | 185 | } |
diff --git a/fs/ntfs/compress.c b/fs/ntfs/compress.c index d98daf59e0b6..d1619d05eb23 100644 --- a/fs/ntfs/compress.c +++ b/fs/ntfs/compress.c | |||
@@ -561,6 +561,16 @@ int ntfs_read_compressed_block(struct page *page) | |||
561 | read_unlock_irqrestore(&ni->size_lock, flags); | 561 | read_unlock_irqrestore(&ni->size_lock, flags); |
562 | max_page = ((i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT) - | 562 | max_page = ((i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT) - |
563 | offset; | 563 | offset; |
564 | /* Is the page fully outside i_size? (truncate in progress) */ | ||
565 | if (xpage >= max_page) { | ||
566 | kfree(bhs); | ||
567 | kfree(pages); | ||
568 | zero_user_page(page, 0, PAGE_CACHE_SIZE, KM_USER0); | ||
569 | ntfs_debug("Compressed read outside i_size - truncated?"); | ||
570 | SetPageUptodate(page); | ||
571 | unlock_page(page); | ||
572 | return 0; | ||
573 | } | ||
564 | if (nr_pages < max_page) | 574 | if (nr_pages < max_page) |
565 | max_page = nr_pages; | 575 | max_page = nr_pages; |
566 | for (i = 0; i < max_page; i++, offset++) { | 576 | for (i = 0; i < max_page; i++, offset++) { |
diff --git a/fs/ntfs/namei.c b/fs/ntfs/namei.c index e93c6142b23c..e1781c8b1650 100644 --- a/fs/ntfs/namei.c +++ b/fs/ntfs/namei.c | |||
@@ -450,58 +450,40 @@ try_next: | |||
450 | return parent_dent; | 450 | return parent_dent; |
451 | } | 451 | } |
452 | 452 | ||
453 | /** | 453 | static struct inode *ntfs_nfs_get_inode(struct super_block *sb, |
454 | * ntfs_get_dentry - find a dentry for the inode from a file handle sub-fragment | 454 | u64 ino, u32 generation) |
455 | * @sb: super block identifying the mounted ntfs volume | ||
456 | * @fh: the file handle sub-fragment | ||
457 | * | ||
458 | * Find a dentry for the inode given a file handle sub-fragment. This function | ||
459 | * is called from fs/exportfs/expfs.c::find_exported_dentry() which in turn is | ||
460 | * called from the default ->decode_fh() which is export_decode_fh() in the | ||
461 | * same file. The code is closely based on the default ->get_dentry() helper | ||
462 | * fs/exportfs/expfs.c::get_object(). | ||
463 | * | ||
464 | * The @fh contains two 32-bit unsigned values, the first one is the inode | ||
465 | * number and the second one is the inode generation. | ||
466 | * | ||
467 | * Return the dentry on success or the error code on error (IS_ERR() is true). | ||
468 | */ | ||
469 | static struct dentry *ntfs_get_dentry(struct super_block *sb, void *fh) | ||
470 | { | 455 | { |
471 | struct inode *vi; | 456 | struct inode *inode; |
472 | struct dentry *dent; | ||
473 | unsigned long ino = ((u32 *)fh)[0]; | ||
474 | u32 gen = ((u32 *)fh)[1]; | ||
475 | 457 | ||
476 | ntfs_debug("Entering for inode 0x%lx, generation 0x%x.", ino, gen); | 458 | inode = ntfs_iget(sb, ino); |
477 | vi = ntfs_iget(sb, ino); | 459 | if (!IS_ERR(inode)) { |
478 | if (IS_ERR(vi)) { | 460 | if (is_bad_inode(inode) || inode->i_generation != generation) { |
479 | ntfs_error(sb, "Failed to get inode 0x%lx.", ino); | 461 | iput(inode); |
480 | return (struct dentry *)vi; | 462 | inode = ERR_PTR(-ESTALE); |
481 | } | 463 | } |
482 | if (unlikely(is_bad_inode(vi) || vi->i_generation != gen)) { | ||
483 | /* We didn't find the right inode. */ | ||
484 | ntfs_error(sb, "Inode 0x%lx, bad count: %d %d or version 0x%x " | ||
485 | "0x%x.", vi->i_ino, vi->i_nlink, | ||
486 | atomic_read(&vi->i_count), vi->i_generation, | ||
487 | gen); | ||
488 | iput(vi); | ||
489 | return ERR_PTR(-ESTALE); | ||
490 | } | ||
491 | /* Now find a dentry. If possible, get a well-connected one. */ | ||
492 | dent = d_alloc_anon(vi); | ||
493 | if (unlikely(!dent)) { | ||
494 | iput(vi); | ||
495 | return ERR_PTR(-ENOMEM); | ||
496 | } | 464 | } |
497 | ntfs_debug("Done for inode 0x%lx, generation 0x%x.", ino, gen); | 465 | |
498 | return dent; | 466 | return inode; |
467 | } | ||
468 | |||
469 | static struct dentry *ntfs_fh_to_dentry(struct super_block *sb, struct fid *fid, | ||
470 | int fh_len, int fh_type) | ||
471 | { | ||
472 | return generic_fh_to_dentry(sb, fid, fh_len, fh_type, | ||
473 | ntfs_nfs_get_inode); | ||
474 | } | ||
475 | |||
476 | static struct dentry *ntfs_fh_to_parent(struct super_block *sb, struct fid *fid, | ||
477 | int fh_len, int fh_type) | ||
478 | { | ||
479 | return generic_fh_to_parent(sb, fid, fh_len, fh_type, | ||
480 | ntfs_nfs_get_inode); | ||
499 | } | 481 | } |
500 | 482 | ||
501 | /** | 483 | /** |
502 | * Export operations allowing NFS exporting of mounted NTFS partitions. | 484 | * Export operations allowing NFS exporting of mounted NTFS partitions. |
503 | * | 485 | * |
504 | * We use the default ->decode_fh() and ->encode_fh() for now. Note that they | 486 | * We use the default ->encode_fh() for now. Note that they |
505 | * use 32 bits to store the inode number which is an unsigned long so on 64-bit | 487 | * use 32 bits to store the inode number which is an unsigned long so on 64-bit |
506 | * architectures is usually 64 bits so it would all fail horribly on huge | 488 | * architectures is usually 64 bits so it would all fail horribly on huge |
507 | * volumes. I guess we need to define our own encode and decode fh functions | 489 | * volumes. I guess we need to define our own encode and decode fh functions |
@@ -517,10 +499,9 @@ static struct dentry *ntfs_get_dentry(struct super_block *sb, void *fh) | |||
517 | * allowing the inode number 0 which is used in NTFS for the system file $MFT | 499 | * allowing the inode number 0 which is used in NTFS for the system file $MFT |
518 | * and due to using iget() whereas NTFS needs ntfs_iget(). | 500 | * and due to using iget() whereas NTFS needs ntfs_iget(). |
519 | */ | 501 | */ |
520 | struct export_operations ntfs_export_ops = { | 502 | const struct export_operations ntfs_export_ops = { |
521 | .get_parent = ntfs_get_parent, /* Find the parent of a given | 503 | .get_parent = ntfs_get_parent, /* Find the parent of a given |
522 | directory. */ | 504 | directory. */ |
523 | .get_dentry = ntfs_get_dentry, /* Find a dentry for the inode | 505 | .fh_to_dentry = ntfs_fh_to_dentry, |
524 | given a file handle | 506 | .fh_to_parent = ntfs_fh_to_parent, |
525 | sub-fragment. */ | ||
526 | }; | 507 | }; |
diff --git a/fs/ntfs/ntfs.h b/fs/ntfs/ntfs.h index d73f5a9ac341..d6a340bf80fc 100644 --- a/fs/ntfs/ntfs.h +++ b/fs/ntfs/ntfs.h | |||
@@ -69,7 +69,7 @@ extern const struct inode_operations ntfs_dir_inode_ops; | |||
69 | extern const struct file_operations ntfs_empty_file_ops; | 69 | extern const struct file_operations ntfs_empty_file_ops; |
70 | extern const struct inode_operations ntfs_empty_inode_ops; | 70 | extern const struct inode_operations ntfs_empty_inode_ops; |
71 | 71 | ||
72 | extern struct export_operations ntfs_export_ops; | 72 | extern const struct export_operations ntfs_export_ops; |
73 | 73 | ||
74 | /** | 74 | /** |
75 | * NTFS_SB - return the ntfs volume given a vfs super block | 75 | * NTFS_SB - return the ntfs volume given a vfs super block |
diff --git a/fs/ntfs/sysctl.c b/fs/ntfs/sysctl.c index 4847fbfb0107..9ef85e628fe1 100644 --- a/fs/ntfs/sysctl.c +++ b/fs/ntfs/sysctl.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * sysctl.c - Code for sysctl handling in NTFS Linux kernel driver. Part of | 2 | * sysctl.c - Code for sysctl handling in NTFS Linux kernel driver. Part of |
3 | * the Linux-NTFS project. Adapted from the old NTFS driver, | 3 | * the Linux-NTFS project. Adapted from the old NTFS driver, |
4 | * Copyright (C) 1997 Martin von Löwis, Régis Duchesne | 4 | * Copyright (C) 1997 Martin von Löwis, Régis Duchesne |
5 | * | 5 | * |
6 | * Copyright (c) 2002-2005 Anton Altaparmakov | 6 | * Copyright (c) 2002-2005 Anton Altaparmakov |
7 | * | 7 | * |
diff --git a/fs/ntfs/sysctl.h b/fs/ntfs/sysctl.h index beda5bf96405..d4f8ce920d95 100644 --- a/fs/ntfs/sysctl.h +++ b/fs/ntfs/sysctl.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * sysctl.h - Defines for sysctl handling in NTFS Linux kernel driver. Part of | 2 | * sysctl.h - Defines for sysctl handling in NTFS Linux kernel driver. Part of |
3 | * the Linux-NTFS project. Adapted from the old NTFS driver, | 3 | * the Linux-NTFS project. Adapted from the old NTFS driver, |
4 | * Copyright (C) 1997 Martin von Löwis, Régis Duchesne | 4 | * Copyright (C) 1997 Martin von Löwis, Régis Duchesne |
5 | * | 5 | * |
6 | * Copyright (c) 2002-2004 Anton Altaparmakov | 6 | * Copyright (c) 2002-2004 Anton Altaparmakov |
7 | * | 7 | * |
diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c index 4ba7f0bdc248..ce62c152823d 100644 --- a/fs/ocfs2/alloc.c +++ b/fs/ocfs2/alloc.c | |||
@@ -3946,7 +3946,7 @@ static int __ocfs2_mark_extent_written(struct inode *inode, | |||
3946 | struct ocfs2_merge_ctxt ctxt; | 3946 | struct ocfs2_merge_ctxt ctxt; |
3947 | struct ocfs2_extent_list *rightmost_el; | 3947 | struct ocfs2_extent_list *rightmost_el; |
3948 | 3948 | ||
3949 | if (!rec->e_flags & OCFS2_EXT_UNWRITTEN) { | 3949 | if (!(rec->e_flags & OCFS2_EXT_UNWRITTEN)) { |
3950 | ret = -EIO; | 3950 | ret = -EIO; |
3951 | mlog_errno(ret); | 3951 | mlog_errno(ret); |
3952 | goto out; | 3952 | goto out; |
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index c69c1b300155..56f7790cad46 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c | |||
@@ -729,6 +729,27 @@ static void ocfs2_clear_page_regions(struct page *page, | |||
729 | } | 729 | } |
730 | 730 | ||
731 | /* | 731 | /* |
732 | * Nonsparse file systems fully allocate before we get to the write | ||
733 | * code. This prevents ocfs2_write() from tagging the write as an | ||
734 | * allocating one, which means ocfs2_map_page_blocks() might try to | ||
735 | * read-in the blocks at the tail of our file. Avoid reading them by | ||
736 | * testing i_size against each block offset. | ||
737 | */ | ||
738 | static int ocfs2_should_read_blk(struct inode *inode, struct page *page, | ||
739 | unsigned int block_start) | ||
740 | { | ||
741 | u64 offset = page_offset(page) + block_start; | ||
742 | |||
743 | if (ocfs2_sparse_alloc(OCFS2_SB(inode->i_sb))) | ||
744 | return 1; | ||
745 | |||
746 | if (i_size_read(inode) > offset) | ||
747 | return 1; | ||
748 | |||
749 | return 0; | ||
750 | } | ||
751 | |||
752 | /* | ||
732 | * Some of this taken from block_prepare_write(). We already have our | 753 | * Some of this taken from block_prepare_write(). We already have our |
733 | * mapping by now though, and the entire write will be allocating or | 754 | * mapping by now though, and the entire write will be allocating or |
734 | * it won't, so not much need to use BH_New. | 755 | * it won't, so not much need to use BH_New. |
@@ -781,6 +802,7 @@ int ocfs2_map_page_blocks(struct page *page, u64 *p_blkno, | |||
781 | set_buffer_uptodate(bh); | 802 | set_buffer_uptodate(bh); |
782 | } else if (!buffer_uptodate(bh) && !buffer_delay(bh) && | 803 | } else if (!buffer_uptodate(bh) && !buffer_delay(bh) && |
783 | !buffer_new(bh) && | 804 | !buffer_new(bh) && |
805 | ocfs2_should_read_blk(inode, page, block_start) && | ||
784 | (block_start < from || block_end > to)) { | 806 | (block_start < from || block_end > to)) { |
785 | ll_rw_block(READ, 1, &bh); | 807 | ll_rw_block(READ, 1, &bh); |
786 | *wait_bh++=bh; | 808 | *wait_bh++=bh; |
@@ -1492,7 +1514,7 @@ int ocfs2_size_fits_inline_data(struct buffer_head *di_bh, u64 new_size) | |||
1492 | { | 1514 | { |
1493 | struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data; | 1515 | struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data; |
1494 | 1516 | ||
1495 | if (new_size < le16_to_cpu(di->id2.i_data.id_count)) | 1517 | if (new_size <= le16_to_cpu(di->id2.i_data.id_count)) |
1496 | return 1; | 1518 | return 1; |
1497 | return 0; | 1519 | return 0; |
1498 | } | 1520 | } |
diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c index f14b541fab95..f02ccb34604d 100644 --- a/fs/ocfs2/cluster/heartbeat.c +++ b/fs/ocfs2/cluster/heartbeat.c | |||
@@ -267,7 +267,7 @@ static struct bio *o2hb_setup_one_bio(struct o2hb_region *reg, | |||
267 | current_page = cs / spp; | 267 | current_page = cs / spp; |
268 | page = reg->hr_slot_data[current_page]; | 268 | page = reg->hr_slot_data[current_page]; |
269 | 269 | ||
270 | vec_len = min(PAGE_CACHE_SIZE, | 270 | vec_len = min(PAGE_CACHE_SIZE - vec_start, |
271 | (max_slots-cs) * (PAGE_CACHE_SIZE/spp) ); | 271 | (max_slots-cs) * (PAGE_CACHE_SIZE/spp) ); |
272 | 272 | ||
273 | mlog(ML_HB_BIO, "page %d, vec_len = %u, vec_start = %u\n", | 273 | mlog(ML_HB_BIO, "page %d, vec_len = %u, vec_start = %u\n", |
@@ -1372,7 +1372,7 @@ static ssize_t o2hb_region_pid_read(struct o2hb_region *reg, | |||
1372 | 1372 | ||
1373 | spin_lock(&o2hb_live_lock); | 1373 | spin_lock(&o2hb_live_lock); |
1374 | if (reg->hr_task) | 1374 | if (reg->hr_task) |
1375 | pid = reg->hr_task->pid; | 1375 | pid = task_pid_nr(reg->hr_task); |
1376 | spin_unlock(&o2hb_live_lock); | 1376 | spin_unlock(&o2hb_live_lock); |
1377 | 1377 | ||
1378 | if (!pid) | 1378 | if (!pid) |
diff --git a/fs/ocfs2/cluster/masklog.h b/fs/ocfs2/cluster/masklog.h index 75cd877f6d42..597e064bb94f 100644 --- a/fs/ocfs2/cluster/masklog.h +++ b/fs/ocfs2/cluster/masklog.h | |||
@@ -192,7 +192,7 @@ extern struct mlog_bits mlog_and_bits, mlog_not_bits; | |||
192 | * previous token if args expands to nothing. | 192 | * previous token if args expands to nothing. |
193 | */ | 193 | */ |
194 | #define __mlog_printk(level, fmt, args...) \ | 194 | #define __mlog_printk(level, fmt, args...) \ |
195 | printk(level "(%u,%lu):%s:%d " fmt, current->pid, \ | 195 | printk(level "(%u,%lu):%s:%d " fmt, task_pid_nr(current), \ |
196 | __mlog_cpu_guess, __PRETTY_FUNCTION__, __LINE__ , \ | 196 | __mlog_cpu_guess, __PRETTY_FUNCTION__, __LINE__ , \ |
197 | ##args) | 197 | ##args) |
198 | 198 | ||
@@ -212,7 +212,7 @@ extern struct mlog_bits mlog_and_bits, mlog_not_bits; | |||
212 | #define mlog_errno(st) do { \ | 212 | #define mlog_errno(st) do { \ |
213 | int _st = (st); \ | 213 | int _st = (st); \ |
214 | if (_st != -ERESTARTSYS && _st != -EINTR && \ | 214 | if (_st != -ERESTARTSYS && _st != -EINTR && \ |
215 | _st != AOP_TRUNCATED_PAGE) \ | 215 | _st != AOP_TRUNCATED_PAGE && _st != -ENOSPC) \ |
216 | mlog(ML_ERROR, "status = %lld\n", (long long)_st); \ | 216 | mlog(ML_ERROR, "status = %lld\n", (long long)_st); \ |
217 | } while (0) | 217 | } while (0) |
218 | 218 | ||
diff --git a/fs/ocfs2/cluster/tcp.c b/fs/ocfs2/cluster/tcp.c index 685c18065c82..ee50c9610e7f 100644 --- a/fs/ocfs2/cluster/tcp.c +++ b/fs/ocfs2/cluster/tcp.c | |||
@@ -58,6 +58,7 @@ | |||
58 | #include <linux/slab.h> | 58 | #include <linux/slab.h> |
59 | #include <linux/idr.h> | 59 | #include <linux/idr.h> |
60 | #include <linux/kref.h> | 60 | #include <linux/kref.h> |
61 | #include <linux/net.h> | ||
61 | #include <net/tcp.h> | 62 | #include <net/tcp.h> |
62 | 63 | ||
63 | #include <asm/uaccess.h> | 64 | #include <asm/uaccess.h> |
@@ -71,14 +72,6 @@ | |||
71 | 72 | ||
72 | #include "tcp_internal.h" | 73 | #include "tcp_internal.h" |
73 | 74 | ||
74 | /* | ||
75 | * The linux network stack isn't sparse endian clean.. It has macros like | ||
76 | * ntohs() which perform the endian checks and structs like sockaddr_in | ||
77 | * which aren't annotated. So __force is found here to get the build | ||
78 | * clean. When they emerge from the dark ages and annotate the code | ||
79 | * we can remove these. | ||
80 | */ | ||
81 | |||
82 | #define SC_NODEF_FMT "node %s (num %u) at %u.%u.%u.%u:%u" | 75 | #define SC_NODEF_FMT "node %s (num %u) at %u.%u.%u.%u:%u" |
83 | #define SC_NODEF_ARGS(sc) sc->sc_node->nd_name, sc->sc_node->nd_num, \ | 76 | #define SC_NODEF_ARGS(sc) sc->sc_node->nd_name, sc->sc_node->nd_num, \ |
84 | NIPQUAD(sc->sc_node->nd_ipv4_address), \ | 77 | NIPQUAD(sc->sc_node->nd_ipv4_address), \ |
@@ -616,8 +609,7 @@ static void o2net_shutdown_sc(struct work_struct *work) | |||
616 | del_timer_sync(&sc->sc_idle_timeout); | 609 | del_timer_sync(&sc->sc_idle_timeout); |
617 | o2net_sc_cancel_delayed_work(sc, &sc->sc_keepalive_work); | 610 | o2net_sc_cancel_delayed_work(sc, &sc->sc_keepalive_work); |
618 | sc_put(sc); | 611 | sc_put(sc); |
619 | sc->sc_sock->ops->shutdown(sc->sc_sock, | 612 | kernel_sock_shutdown(sc->sc_sock, SHUT_RDWR); |
620 | RCV_SHUTDOWN|SEND_SHUTDOWN); | ||
621 | } | 613 | } |
622 | 614 | ||
623 | /* not fatal so failed connects before the other guy has our | 615 | /* not fatal so failed connects before the other guy has our |
@@ -1500,7 +1492,7 @@ static void o2net_start_connect(struct work_struct *work) | |||
1500 | 1492 | ||
1501 | myaddr.sin_family = AF_INET; | 1493 | myaddr.sin_family = AF_INET; |
1502 | myaddr.sin_addr.s_addr = mynode->nd_ipv4_address; | 1494 | myaddr.sin_addr.s_addr = mynode->nd_ipv4_address; |
1503 | myaddr.sin_port = (__force u16)htons(0); /* any port */ | 1495 | myaddr.sin_port = htons(0); /* any port */ |
1504 | 1496 | ||
1505 | ret = sock->ops->bind(sock, (struct sockaddr *)&myaddr, | 1497 | ret = sock->ops->bind(sock, (struct sockaddr *)&myaddr, |
1506 | sizeof(myaddr)); | 1498 | sizeof(myaddr)); |
@@ -1701,11 +1693,11 @@ static int o2net_accept_one(struct socket *sock) | |||
1701 | if (ret < 0) | 1693 | if (ret < 0) |
1702 | goto out; | 1694 | goto out; |
1703 | 1695 | ||
1704 | node = o2nm_get_node_by_ip((__force __be32)sin.sin_addr.s_addr); | 1696 | node = o2nm_get_node_by_ip(sin.sin_addr.s_addr); |
1705 | if (node == NULL) { | 1697 | if (node == NULL) { |
1706 | mlog(ML_NOTICE, "attempt to connect from unknown node at " | 1698 | mlog(ML_NOTICE, "attempt to connect from unknown node at " |
1707 | "%u.%u.%u.%u:%d\n", NIPQUAD(sin.sin_addr.s_addr), | 1699 | "%u.%u.%u.%u:%d\n", NIPQUAD(sin.sin_addr.s_addr), |
1708 | ntohs((__force __be16)sin.sin_port)); | 1700 | ntohs(sin.sin_port)); |
1709 | ret = -EINVAL; | 1701 | ret = -EINVAL; |
1710 | goto out; | 1702 | goto out; |
1711 | } | 1703 | } |
@@ -1714,7 +1706,7 @@ static int o2net_accept_one(struct socket *sock) | |||
1714 | mlog(ML_NOTICE, "unexpected connect attempted from a lower " | 1706 | mlog(ML_NOTICE, "unexpected connect attempted from a lower " |
1715 | "numbered node '%s' at " "%u.%u.%u.%u:%d with num %u\n", | 1707 | "numbered node '%s' at " "%u.%u.%u.%u:%d with num %u\n", |
1716 | node->nd_name, NIPQUAD(sin.sin_addr.s_addr), | 1708 | node->nd_name, NIPQUAD(sin.sin_addr.s_addr), |
1717 | ntohs((__force __be16)sin.sin_port), node->nd_num); | 1709 | ntohs(sin.sin_port), node->nd_num); |
1718 | ret = -EINVAL; | 1710 | ret = -EINVAL; |
1719 | goto out; | 1711 | goto out; |
1720 | } | 1712 | } |
@@ -1725,7 +1717,7 @@ static int o2net_accept_one(struct socket *sock) | |||
1725 | mlog(ML_CONN, "attempt to connect from node '%s' at " | 1717 | mlog(ML_CONN, "attempt to connect from node '%s' at " |
1726 | "%u.%u.%u.%u:%d but it isn't heartbeating\n", | 1718 | "%u.%u.%u.%u:%d but it isn't heartbeating\n", |
1727 | node->nd_name, NIPQUAD(sin.sin_addr.s_addr), | 1719 | node->nd_name, NIPQUAD(sin.sin_addr.s_addr), |
1728 | ntohs((__force __be16)sin.sin_port)); | 1720 | ntohs(sin.sin_port)); |
1729 | ret = -EINVAL; | 1721 | ret = -EINVAL; |
1730 | goto out; | 1722 | goto out; |
1731 | } | 1723 | } |
@@ -1742,7 +1734,7 @@ static int o2net_accept_one(struct socket *sock) | |||
1742 | mlog(ML_NOTICE, "attempt to connect from node '%s' at " | 1734 | mlog(ML_NOTICE, "attempt to connect from node '%s' at " |
1743 | "%u.%u.%u.%u:%d but it already has an open connection\n", | 1735 | "%u.%u.%u.%u:%d but it already has an open connection\n", |
1744 | node->nd_name, NIPQUAD(sin.sin_addr.s_addr), | 1736 | node->nd_name, NIPQUAD(sin.sin_addr.s_addr), |
1745 | ntohs((__force __be16)sin.sin_port)); | 1737 | ntohs(sin.sin_port)); |
1746 | goto out; | 1738 | goto out; |
1747 | } | 1739 | } |
1748 | 1740 | ||
diff --git a/fs/ocfs2/dcache.c b/fs/ocfs2/dcache.c index 014e73978dac..9923278ea6d4 100644 --- a/fs/ocfs2/dcache.c +++ b/fs/ocfs2/dcache.c | |||
@@ -318,9 +318,9 @@ out_attach: | |||
318 | static void ocfs2_drop_dentry_lock(struct ocfs2_super *osb, | 318 | static void ocfs2_drop_dentry_lock(struct ocfs2_super *osb, |
319 | struct ocfs2_dentry_lock *dl) | 319 | struct ocfs2_dentry_lock *dl) |
320 | { | 320 | { |
321 | iput(dl->dl_inode); | ||
321 | ocfs2_simple_drop_lockres(osb, &dl->dl_lockres); | 322 | ocfs2_simple_drop_lockres(osb, &dl->dl_lockres); |
322 | ocfs2_lock_res_free(&dl->dl_lockres); | 323 | ocfs2_lock_res_free(&dl->dl_lockres); |
323 | iput(dl->dl_inode); | ||
324 | kfree(dl); | 324 | kfree(dl); |
325 | } | 325 | } |
326 | 326 | ||
@@ -344,12 +344,24 @@ static void ocfs2_dentry_iput(struct dentry *dentry, struct inode *inode) | |||
344 | { | 344 | { |
345 | struct ocfs2_dentry_lock *dl = dentry->d_fsdata; | 345 | struct ocfs2_dentry_lock *dl = dentry->d_fsdata; |
346 | 346 | ||
347 | mlog_bug_on_msg(!dl && !(dentry->d_flags & DCACHE_DISCONNECTED), | 347 | if (!dl) { |
348 | "dentry: %.*s\n", dentry->d_name.len, | 348 | /* |
349 | dentry->d_name.name); | 349 | * No dentry lock is ok if we're disconnected or |
350 | * unhashed. | ||
351 | */ | ||
352 | if (!(dentry->d_flags & DCACHE_DISCONNECTED) && | ||
353 | !d_unhashed(dentry)) { | ||
354 | unsigned long long ino = 0ULL; | ||
355 | if (inode) | ||
356 | ino = (unsigned long long)OCFS2_I(inode)->ip_blkno; | ||
357 | mlog(ML_ERROR, "Dentry is missing cluster lock. " | ||
358 | "inode: %llu, d_flags: 0x%x, d_name: %.*s\n", | ||
359 | ino, dentry->d_flags, dentry->d_name.len, | ||
360 | dentry->d_name.name); | ||
361 | } | ||
350 | 362 | ||
351 | if (!dl) | ||
352 | goto out; | 363 | goto out; |
364 | } | ||
353 | 365 | ||
354 | mlog_bug_on_msg(dl->dl_count == 0, "dentry: %.*s, count: %u\n", | 366 | mlog_bug_on_msg(dl->dl_count == 0, "dentry: %.*s, count: %u\n", |
355 | dentry->d_name.len, dentry->d_name.name, | 367 | dentry->d_name.len, dentry->d_name.name, |
@@ -376,7 +388,7 @@ out: | |||
376 | * directory locks. The dentries have already been deleted on other | 388 | * directory locks. The dentries have already been deleted on other |
377 | * nodes via ocfs2_remote_dentry_delete(). | 389 | * nodes via ocfs2_remote_dentry_delete(). |
378 | * | 390 | * |
379 | * Normally, the VFS handles the d_move() for the file sytem, after | 391 | * Normally, the VFS handles the d_move() for the file system, after |
380 | * the ->rename() callback. OCFS2 wants to handle this internally, so | 392 | * the ->rename() callback. OCFS2 wants to handle this internally, so |
381 | * the new lock can be created atomically with respect to the cluster. | 393 | * the new lock can be created atomically with respect to the cluster. |
382 | */ | 394 | */ |
diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c index 6a2f143e269c..63b28fdceb4a 100644 --- a/fs/ocfs2/dir.c +++ b/fs/ocfs2/dir.c | |||
@@ -208,9 +208,9 @@ out: | |||
208 | return NULL; | 208 | return NULL; |
209 | } | 209 | } |
210 | 210 | ||
211 | struct buffer_head *ocfs2_find_entry_el(const char *name, int namelen, | 211 | static struct buffer_head *ocfs2_find_entry_el(const char *name, int namelen, |
212 | struct inode *dir, | 212 | struct inode *dir, |
213 | struct ocfs2_dir_entry **res_dir) | 213 | struct ocfs2_dir_entry **res_dir) |
214 | { | 214 | { |
215 | struct super_block *sb; | 215 | struct super_block *sb; |
216 | struct buffer_head *bh_use[NAMEI_RA_SIZE]; | 216 | struct buffer_head *bh_use[NAMEI_RA_SIZE]; |
diff --git a/fs/ocfs2/dlm/dlmmaster.c b/fs/ocfs2/dlm/dlmmaster.c index 62e4a7daa286..a54d33d95ada 100644 --- a/fs/ocfs2/dlm/dlmmaster.c +++ b/fs/ocfs2/dlm/dlmmaster.c | |||
@@ -908,7 +908,7 @@ lookup: | |||
908 | * but they might own this lockres. wait on them. */ | 908 | * but they might own this lockres. wait on them. */ |
909 | bit = find_next_bit(dlm->recovery_map, O2NM_MAX_NODES, 0); | 909 | bit = find_next_bit(dlm->recovery_map, O2NM_MAX_NODES, 0); |
910 | if (bit < O2NM_MAX_NODES) { | 910 | if (bit < O2NM_MAX_NODES) { |
911 | mlog(ML_NOTICE, "%s:%.*s: at least one node (%d) to" | 911 | mlog(ML_NOTICE, "%s:%.*s: at least one node (%d) to " |
912 | "recover before lock mastery can begin\n", | 912 | "recover before lock mastery can begin\n", |
913 | dlm->name, namelen, (char *)lockid, bit); | 913 | dlm->name, namelen, (char *)lockid, bit); |
914 | wait_on_recovery = 1; | 914 | wait_on_recovery = 1; |
@@ -962,7 +962,7 @@ redo_request: | |||
962 | spin_lock(&dlm->spinlock); | 962 | spin_lock(&dlm->spinlock); |
963 | bit = find_next_bit(dlm->recovery_map, O2NM_MAX_NODES, 0); | 963 | bit = find_next_bit(dlm->recovery_map, O2NM_MAX_NODES, 0); |
964 | if (bit < O2NM_MAX_NODES) { | 964 | if (bit < O2NM_MAX_NODES) { |
965 | mlog(ML_NOTICE, "%s:%.*s: at least one node (%d) to" | 965 | mlog(ML_NOTICE, "%s:%.*s: at least one node (%d) to " |
966 | "recover before lock mastery can begin\n", | 966 | "recover before lock mastery can begin\n", |
967 | dlm->name, namelen, (char *)lockid, bit); | 967 | dlm->name, namelen, (char *)lockid, bit); |
968 | wait_on_recovery = 1; | 968 | wait_on_recovery = 1; |
diff --git a/fs/ocfs2/dlm/dlmrecovery.c b/fs/ocfs2/dlm/dlmrecovery.c index a2c33160bfd6..2fde7bf91434 100644 --- a/fs/ocfs2/dlm/dlmrecovery.c +++ b/fs/ocfs2/dlm/dlmrecovery.c | |||
@@ -259,7 +259,7 @@ static void dlm_print_reco_node_status(struct dlm_ctxt *dlm) | |||
259 | struct dlm_lock_resource *res; | 259 | struct dlm_lock_resource *res; |
260 | 260 | ||
261 | mlog(ML_NOTICE, "%s(%d): recovery info, state=%s, dead=%u, master=%u\n", | 261 | mlog(ML_NOTICE, "%s(%d): recovery info, state=%s, dead=%u, master=%u\n", |
262 | dlm->name, dlm->dlm_reco_thread_task->pid, | 262 | dlm->name, task_pid_nr(dlm->dlm_reco_thread_task), |
263 | dlm->reco.state & DLM_RECO_STATE_ACTIVE ? "ACTIVE" : "inactive", | 263 | dlm->reco.state & DLM_RECO_STATE_ACTIVE ? "ACTIVE" : "inactive", |
264 | dlm->reco.dead_node, dlm->reco.new_master); | 264 | dlm->reco.dead_node, dlm->reco.new_master); |
265 | 265 | ||
@@ -420,7 +420,7 @@ void dlm_wait_for_recovery(struct dlm_ctxt *dlm) | |||
420 | if (dlm_in_recovery(dlm)) { | 420 | if (dlm_in_recovery(dlm)) { |
421 | mlog(0, "%s: reco thread %d in recovery: " | 421 | mlog(0, "%s: reco thread %d in recovery: " |
422 | "state=%d, master=%u, dead=%u\n", | 422 | "state=%d, master=%u, dead=%u\n", |
423 | dlm->name, dlm->dlm_reco_thread_task->pid, | 423 | dlm->name, task_pid_nr(dlm->dlm_reco_thread_task), |
424 | dlm->reco.state, dlm->reco.new_master, | 424 | dlm->reco.state, dlm->reco.new_master, |
425 | dlm->reco.dead_node); | 425 | dlm->reco.dead_node); |
426 | } | 426 | } |
@@ -483,7 +483,7 @@ static int dlm_do_recovery(struct dlm_ctxt *dlm) | |||
483 | return 0; | 483 | return 0; |
484 | } | 484 | } |
485 | mlog(0, "%s(%d):recovery thread found node %u in the recovery map!\n", | 485 | mlog(0, "%s(%d):recovery thread found node %u in the recovery map!\n", |
486 | dlm->name, dlm->dlm_reco_thread_task->pid, | 486 | dlm->name, task_pid_nr(dlm->dlm_reco_thread_task), |
487 | dlm->reco.dead_node); | 487 | dlm->reco.dead_node); |
488 | spin_unlock(&dlm->spinlock); | 488 | spin_unlock(&dlm->spinlock); |
489 | 489 | ||
@@ -507,7 +507,7 @@ static int dlm_do_recovery(struct dlm_ctxt *dlm) | |||
507 | mlog(0, "another node will master this recovery session.\n"); | 507 | mlog(0, "another node will master this recovery session.\n"); |
508 | } | 508 | } |
509 | mlog(0, "dlm=%s (%d), new_master=%u, this node=%u, dead_node=%u\n", | 509 | mlog(0, "dlm=%s (%d), new_master=%u, this node=%u, dead_node=%u\n", |
510 | dlm->name, dlm->dlm_reco_thread_task->pid, dlm->reco.new_master, | 510 | dlm->name, task_pid_nr(dlm->dlm_reco_thread_task), dlm->reco.new_master, |
511 | dlm->node_num, dlm->reco.dead_node); | 511 | dlm->node_num, dlm->reco.dead_node); |
512 | 512 | ||
513 | /* it is safe to start everything back up here | 513 | /* it is safe to start everything back up here |
@@ -520,7 +520,7 @@ static int dlm_do_recovery(struct dlm_ctxt *dlm) | |||
520 | 520 | ||
521 | master_here: | 521 | master_here: |
522 | mlog(0, "(%d) mastering recovery of %s:%u here(this=%u)!\n", | 522 | mlog(0, "(%d) mastering recovery of %s:%u here(this=%u)!\n", |
523 | dlm->dlm_reco_thread_task->pid, | 523 | task_pid_nr(dlm->dlm_reco_thread_task), |
524 | dlm->name, dlm->reco.dead_node, dlm->node_num); | 524 | dlm->name, dlm->reco.dead_node, dlm->node_num); |
525 | 525 | ||
526 | status = dlm_remaster_locks(dlm, dlm->reco.dead_node); | 526 | status = dlm_remaster_locks(dlm, dlm->reco.dead_node); |
diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c index 41c76ff2fcfb..4e97dcceaf8f 100644 --- a/fs/ocfs2/dlmglue.c +++ b/fs/ocfs2/dlmglue.c | |||
@@ -670,7 +670,7 @@ static inline void ocfs2_generic_handle_attach_action(struct ocfs2_lock_res *loc | |||
670 | { | 670 | { |
671 | mlog_entry_void(); | 671 | mlog_entry_void(); |
672 | 672 | ||
673 | BUG_ON((!lockres->l_flags & OCFS2_LOCK_BUSY)); | 673 | BUG_ON((!(lockres->l_flags & OCFS2_LOCK_BUSY))); |
674 | BUG_ON(lockres->l_flags & OCFS2_LOCK_ATTACHED); | 674 | BUG_ON(lockres->l_flags & OCFS2_LOCK_ATTACHED); |
675 | 675 | ||
676 | if (lockres->l_requested > LKM_NLMODE && | 676 | if (lockres->l_requested > LKM_NLMODE && |
@@ -980,18 +980,6 @@ again: | |||
980 | goto unlock; | 980 | goto unlock; |
981 | } | 981 | } |
982 | 982 | ||
983 | if (!(lockres->l_flags & OCFS2_LOCK_ATTACHED)) { | ||
984 | /* lock has not been created yet. */ | ||
985 | spin_unlock_irqrestore(&lockres->l_lock, flags); | ||
986 | |||
987 | ret = ocfs2_lock_create(osb, lockres, LKM_NLMODE, 0); | ||
988 | if (ret < 0) { | ||
989 | mlog_errno(ret); | ||
990 | goto out; | ||
991 | } | ||
992 | goto again; | ||
993 | } | ||
994 | |||
995 | if (lockres->l_flags & OCFS2_LOCK_BLOCKED && | 983 | if (lockres->l_flags & OCFS2_LOCK_BLOCKED && |
996 | !ocfs2_may_continue_on_blocked_lock(lockres, level)) { | 984 | !ocfs2_may_continue_on_blocked_lock(lockres, level)) { |
997 | /* is the lock is currently blocked on behalf of | 985 | /* is the lock is currently blocked on behalf of |
@@ -1006,7 +994,14 @@ again: | |||
1006 | mlog(ML_ERROR, "lockres %s has action %u pending\n", | 994 | mlog(ML_ERROR, "lockres %s has action %u pending\n", |
1007 | lockres->l_name, lockres->l_action); | 995 | lockres->l_name, lockres->l_action); |
1008 | 996 | ||
1009 | lockres->l_action = OCFS2_AST_CONVERT; | 997 | if (!(lockres->l_flags & OCFS2_LOCK_ATTACHED)) { |
998 | lockres->l_action = OCFS2_AST_ATTACH; | ||
999 | lkm_flags &= ~LKM_CONVERT; | ||
1000 | } else { | ||
1001 | lockres->l_action = OCFS2_AST_CONVERT; | ||
1002 | lkm_flags |= LKM_CONVERT; | ||
1003 | } | ||
1004 | |||
1010 | lockres->l_requested = level; | 1005 | lockres->l_requested = level; |
1011 | lockres_or_flags(lockres, OCFS2_LOCK_BUSY); | 1006 | lockres_or_flags(lockres, OCFS2_LOCK_BUSY); |
1012 | spin_unlock_irqrestore(&lockres->l_lock, flags); | 1007 | spin_unlock_irqrestore(&lockres->l_lock, flags); |
@@ -1021,7 +1016,7 @@ again: | |||
1021 | status = dlmlock(osb->dlm, | 1016 | status = dlmlock(osb->dlm, |
1022 | level, | 1017 | level, |
1023 | &lockres->l_lksb, | 1018 | &lockres->l_lksb, |
1024 | lkm_flags|LKM_CONVERT, | 1019 | lkm_flags, |
1025 | lockres->l_name, | 1020 | lockres->l_name, |
1026 | OCFS2_LOCK_ID_MAX_LEN - 1, | 1021 | OCFS2_LOCK_ID_MAX_LEN - 1, |
1027 | ocfs2_locking_ast, | 1022 | ocfs2_locking_ast, |
diff --git a/fs/ocfs2/export.c b/fs/ocfs2/export.c index c3bbc198f9ce..535bfa9568a4 100644 --- a/fs/ocfs2/export.c +++ b/fs/ocfs2/export.c | |||
@@ -45,9 +45,9 @@ struct ocfs2_inode_handle | |||
45 | u32 ih_generation; | 45 | u32 ih_generation; |
46 | }; | 46 | }; |
47 | 47 | ||
48 | static struct dentry *ocfs2_get_dentry(struct super_block *sb, void *vobjp) | 48 | static struct dentry *ocfs2_get_dentry(struct super_block *sb, |
49 | struct ocfs2_inode_handle *handle) | ||
49 | { | 50 | { |
50 | struct ocfs2_inode_handle *handle = vobjp; | ||
51 | struct inode *inode; | 51 | struct inode *inode; |
52 | struct dentry *result; | 52 | struct dentry *result; |
53 | 53 | ||
@@ -194,54 +194,37 @@ bail: | |||
194 | return type; | 194 | return type; |
195 | } | 195 | } |
196 | 196 | ||
197 | static struct dentry *ocfs2_decode_fh(struct super_block *sb, u32 *fh_in, | 197 | static struct dentry *ocfs2_fh_to_dentry(struct super_block *sb, |
198 | int fh_len, int fileid_type, | 198 | struct fid *fid, int fh_len, int fh_type) |
199 | int (*acceptable)(void *context, | ||
200 | struct dentry *de), | ||
201 | void *context) | ||
202 | { | 199 | { |
203 | struct ocfs2_inode_handle handle, parent; | 200 | struct ocfs2_inode_handle handle; |
204 | struct dentry *ret = NULL; | ||
205 | __le32 *fh = (__force __le32 *) fh_in; | ||
206 | |||
207 | mlog_entry("(0x%p, 0x%p, %d, %d, 0x%p, 0x%p)\n", | ||
208 | sb, fh, fh_len, fileid_type, acceptable, context); | ||
209 | |||
210 | if (fh_len < 3 || fileid_type > 2) | ||
211 | goto bail; | ||
212 | |||
213 | if (fileid_type == 2) { | ||
214 | if (fh_len < 6) | ||
215 | goto bail; | ||
216 | |||
217 | parent.ih_blkno = (u64)le32_to_cpu(fh[3]) << 32; | ||
218 | parent.ih_blkno |= (u64)le32_to_cpu(fh[4]); | ||
219 | parent.ih_generation = le32_to_cpu(fh[5]); | ||
220 | 201 | ||
221 | mlog(0, "Decoding parent: blkno: %llu, generation: %u\n", | 202 | if (fh_len < 3 || fh_type > 2) |
222 | (unsigned long long)parent.ih_blkno, | 203 | return NULL; |
223 | parent.ih_generation); | ||
224 | } | ||
225 | 204 | ||
226 | handle.ih_blkno = (u64)le32_to_cpu(fh[0]) << 32; | 205 | handle.ih_blkno = (u64)le32_to_cpu(fid->raw[0]) << 32; |
227 | handle.ih_blkno |= (u64)le32_to_cpu(fh[1]); | 206 | handle.ih_blkno |= (u64)le32_to_cpu(fid->raw[1]); |
228 | handle.ih_generation = le32_to_cpu(fh[2]); | 207 | handle.ih_generation = le32_to_cpu(fid->raw[2]); |
208 | return ocfs2_get_dentry(sb, &handle); | ||
209 | } | ||
229 | 210 | ||
230 | mlog(0, "Encoding fh: blkno: %llu, generation: %u\n", | 211 | static struct dentry *ocfs2_fh_to_parent(struct super_block *sb, |
231 | (unsigned long long)handle.ih_blkno, handle.ih_generation); | 212 | struct fid *fid, int fh_len, int fh_type) |
213 | { | ||
214 | struct ocfs2_inode_handle parent; | ||
232 | 215 | ||
233 | ret = ocfs2_export_ops.find_exported_dentry(sb, &handle, &parent, | 216 | if (fh_type != 2 || fh_len < 6) |
234 | acceptable, context); | 217 | return NULL; |
235 | 218 | ||
236 | bail: | 219 | parent.ih_blkno = (u64)le32_to_cpu(fid->raw[3]) << 32; |
237 | mlog_exit_ptr(ret); | 220 | parent.ih_blkno |= (u64)le32_to_cpu(fid->raw[4]); |
238 | return ret; | 221 | parent.ih_generation = le32_to_cpu(fid->raw[5]); |
222 | return ocfs2_get_dentry(sb, &parent); | ||
239 | } | 223 | } |
240 | 224 | ||
241 | struct export_operations ocfs2_export_ops = { | 225 | const struct export_operations ocfs2_export_ops = { |
242 | .decode_fh = ocfs2_decode_fh, | ||
243 | .encode_fh = ocfs2_encode_fh, | 226 | .encode_fh = ocfs2_encode_fh, |
244 | 227 | .fh_to_dentry = ocfs2_fh_to_dentry, | |
228 | .fh_to_parent = ocfs2_fh_to_parent, | ||
245 | .get_parent = ocfs2_get_parent, | 229 | .get_parent = ocfs2_get_parent, |
246 | .get_dentry = ocfs2_get_dentry, | ||
247 | }; | 230 | }; |
diff --git a/fs/ocfs2/export.h b/fs/ocfs2/export.h index e08bed9e45a0..41a738678c37 100644 --- a/fs/ocfs2/export.h +++ b/fs/ocfs2/export.h | |||
@@ -28,6 +28,6 @@ | |||
28 | 28 | ||
29 | #include <linux/exportfs.h> | 29 | #include <linux/exportfs.h> |
30 | 30 | ||
31 | extern struct export_operations ocfs2_export_ops; | 31 | extern const struct export_operations ocfs2_export_ops; |
32 | 32 | ||
33 | #endif /* OCFS2_EXPORT_H */ | 33 | #endif /* OCFS2_EXPORT_H */ |
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index f92fe91ff260..b75b2e1f0e42 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c | |||
@@ -399,7 +399,7 @@ static int ocfs2_truncate_file(struct inode *inode, | |||
399 | 399 | ||
400 | if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) { | 400 | if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) { |
401 | status = ocfs2_truncate_inline(inode, di_bh, new_i_size, | 401 | status = ocfs2_truncate_inline(inode, di_bh, new_i_size, |
402 | i_size_read(inode), 0); | 402 | i_size_read(inode), 1); |
403 | if (status) | 403 | if (status) |
404 | mlog_errno(status); | 404 | mlog_errno(status); |
405 | 405 | ||
@@ -1521,6 +1521,7 @@ static int ocfs2_remove_inode_range(struct inode *inode, | |||
1521 | u32 trunc_start, trunc_len, cpos, phys_cpos, alloc_size; | 1521 | u32 trunc_start, trunc_len, cpos, phys_cpos, alloc_size; |
1522 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | 1522 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); |
1523 | struct ocfs2_cached_dealloc_ctxt dealloc; | 1523 | struct ocfs2_cached_dealloc_ctxt dealloc; |
1524 | struct address_space *mapping = inode->i_mapping; | ||
1524 | 1525 | ||
1525 | ocfs2_init_dealloc_ctxt(&dealloc); | 1526 | ocfs2_init_dealloc_ctxt(&dealloc); |
1526 | 1527 | ||
@@ -1529,10 +1530,20 @@ static int ocfs2_remove_inode_range(struct inode *inode, | |||
1529 | 1530 | ||
1530 | if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) { | 1531 | if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) { |
1531 | ret = ocfs2_truncate_inline(inode, di_bh, byte_start, | 1532 | ret = ocfs2_truncate_inline(inode, di_bh, byte_start, |
1532 | byte_start + byte_len, 1); | 1533 | byte_start + byte_len, 0); |
1533 | if (ret) | 1534 | if (ret) { |
1534 | mlog_errno(ret); | 1535 | mlog_errno(ret); |
1535 | return ret; | 1536 | goto out; |
1537 | } | ||
1538 | /* | ||
1539 | * There's no need to get fancy with the page cache | ||
1540 | * truncate of an inline-data inode. We're talking | ||
1541 | * about less than a page here, which will be cached | ||
1542 | * in the dinode buffer anyway. | ||
1543 | */ | ||
1544 | unmap_mapping_range(mapping, 0, 0, 0); | ||
1545 | truncate_inode_pages(mapping, 0); | ||
1546 | goto out; | ||
1536 | } | 1547 | } |
1537 | 1548 | ||
1538 | trunc_start = ocfs2_clusters_for_bytes(osb->sb, byte_start); | 1549 | trunc_start = ocfs2_clusters_for_bytes(osb->sb, byte_start); |
@@ -1891,9 +1902,11 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb, | |||
1891 | ssize_t written = 0; | 1902 | ssize_t written = 0; |
1892 | size_t ocount; /* original count */ | 1903 | size_t ocount; /* original count */ |
1893 | size_t count; /* after file limit checks */ | 1904 | size_t count; /* after file limit checks */ |
1894 | loff_t *ppos = &iocb->ki_pos; | 1905 | loff_t old_size, *ppos = &iocb->ki_pos; |
1906 | u32 old_clusters; | ||
1895 | struct file *file = iocb->ki_filp; | 1907 | struct file *file = iocb->ki_filp; |
1896 | struct inode *inode = file->f_path.dentry->d_inode; | 1908 | struct inode *inode = file->f_path.dentry->d_inode; |
1909 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | ||
1897 | 1910 | ||
1898 | mlog_entry("(0x%p, %u, '%.*s')\n", file, | 1911 | mlog_entry("(0x%p, %u, '%.*s')\n", file, |
1899 | (unsigned int)nr_segs, | 1912 | (unsigned int)nr_segs, |
@@ -1949,6 +1962,13 @@ relock: | |||
1949 | goto relock; | 1962 | goto relock; |
1950 | } | 1963 | } |
1951 | 1964 | ||
1965 | /* | ||
1966 | * To later detect whether a journal commit for sync writes is | ||
1967 | * necessary, we sample i_size, and cluster count here. | ||
1968 | */ | ||
1969 | old_size = i_size_read(inode); | ||
1970 | old_clusters = OCFS2_I(inode)->ip_clusters; | ||
1971 | |||
1952 | /* communicate with ocfs2_dio_end_io */ | 1972 | /* communicate with ocfs2_dio_end_io */ |
1953 | ocfs2_iocb_set_rw_locked(iocb, rw_level); | 1973 | ocfs2_iocb_set_rw_locked(iocb, rw_level); |
1954 | 1974 | ||
@@ -1978,6 +1998,21 @@ out_dio: | |||
1978 | /* buffered aio wouldn't have proper lock coverage today */ | 1998 | /* buffered aio wouldn't have proper lock coverage today */ |
1979 | BUG_ON(ret == -EIOCBQUEUED && !(file->f_flags & O_DIRECT)); | 1999 | BUG_ON(ret == -EIOCBQUEUED && !(file->f_flags & O_DIRECT)); |
1980 | 2000 | ||
2001 | if ((file->f_flags & O_SYNC && !direct_io) || IS_SYNC(inode)) { | ||
2002 | /* | ||
2003 | * The generic write paths have handled getting data | ||
2004 | * to disk, but since we don't make use of the dirty | ||
2005 | * inode list, a manual journal commit is necessary | ||
2006 | * here. | ||
2007 | */ | ||
2008 | if (old_size != i_size_read(inode) || | ||
2009 | old_clusters != OCFS2_I(inode)->ip_clusters) { | ||
2010 | ret = journal_force_commit(osb->journal->j_journal); | ||
2011 | if (ret < 0) | ||
2012 | written = ret; | ||
2013 | } | ||
2014 | } | ||
2015 | |||
1981 | /* | 2016 | /* |
1982 | * deep in g_f_a_w_n()->ocfs2_direct_IO we pass in a ocfs2_dio_end_io | 2017 | * deep in g_f_a_w_n()->ocfs2_direct_IO we pass in a ocfs2_dio_end_io |
1983 | * function pointer which is called when o_direct io completes so that | 2018 | * function pointer which is called when o_direct io completes so that |
diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c index 1d5e0cb0fda1..ebb2bbe30f35 100644 --- a/fs/ocfs2/inode.c +++ b/fs/ocfs2/inode.c | |||
@@ -455,8 +455,8 @@ static int ocfs2_read_locked_inode(struct inode *inode, | |||
455 | status = -EINVAL; | 455 | status = -EINVAL; |
456 | fe = (struct ocfs2_dinode *) bh->b_data; | 456 | fe = (struct ocfs2_dinode *) bh->b_data; |
457 | if (!OCFS2_IS_VALID_DINODE(fe)) { | 457 | if (!OCFS2_IS_VALID_DINODE(fe)) { |
458 | mlog(ML_ERROR, "Invalid dinode #%llu: signature = %.*s\n", | 458 | mlog(0, "Invalid dinode #%llu: signature = %.*s\n", |
459 | (unsigned long long)le64_to_cpu(fe->i_blkno), 7, | 459 | (unsigned long long)args->fi_blkno, 7, |
460 | fe->i_signature); | 460 | fe->i_signature); |
461 | goto bail; | 461 | goto bail; |
462 | } | 462 | } |
@@ -863,7 +863,7 @@ static int ocfs2_query_inode_wipe(struct inode *inode, | |||
863 | status = ocfs2_try_open_lock(inode, 1); | 863 | status = ocfs2_try_open_lock(inode, 1); |
864 | if (status == -EAGAIN) { | 864 | if (status == -EAGAIN) { |
865 | status = 0; | 865 | status = 0; |
866 | mlog(0, "Skipping delete of %llu because it is in use on" | 866 | mlog(0, "Skipping delete of %llu because it is in use on " |
867 | "other nodes\n", (unsigned long long)oi->ip_blkno); | 867 | "other nodes\n", (unsigned long long)oi->ip_blkno); |
868 | goto bail; | 868 | goto bail; |
869 | } | 869 | } |
diff --git a/fs/ocfs2/localalloc.c b/fs/ocfs2/localalloc.c index d272847d5a07..58ea88b5af36 100644 --- a/fs/ocfs2/localalloc.c +++ b/fs/ocfs2/localalloc.c | |||
@@ -484,6 +484,7 @@ int ocfs2_reserve_local_alloc_bits(struct ocfs2_super *osb, | |||
484 | 484 | ||
485 | alloc = (struct ocfs2_dinode *) osb->local_alloc_bh->b_data; | 485 | alloc = (struct ocfs2_dinode *) osb->local_alloc_bh->b_data; |
486 | 486 | ||
487 | #ifdef OCFS2_DEBUG_FS | ||
487 | if (le32_to_cpu(alloc->id1.bitmap1.i_used) != | 488 | if (le32_to_cpu(alloc->id1.bitmap1.i_used) != |
488 | ocfs2_local_alloc_count_bits(alloc)) { | 489 | ocfs2_local_alloc_count_bits(alloc)) { |
489 | ocfs2_error(osb->sb, "local alloc inode %llu says it has " | 490 | ocfs2_error(osb->sb, "local alloc inode %llu says it has " |
@@ -494,6 +495,7 @@ int ocfs2_reserve_local_alloc_bits(struct ocfs2_super *osb, | |||
494 | status = -EIO; | 495 | status = -EIO; |
495 | goto bail; | 496 | goto bail; |
496 | } | 497 | } |
498 | #endif | ||
497 | 499 | ||
498 | free_bits = le32_to_cpu(alloc->id1.bitmap1.i_total) - | 500 | free_bits = le32_to_cpu(alloc->id1.bitmap1.i_total) - |
499 | le32_to_cpu(alloc->id1.bitmap1.i_used); | 501 | le32_to_cpu(alloc->id1.bitmap1.i_used); |
@@ -712,9 +714,8 @@ static int ocfs2_sync_local_to_main(struct ocfs2_super *osb, | |||
712 | void *bitmap; | 714 | void *bitmap; |
713 | struct ocfs2_local_alloc *la = OCFS2_LOCAL_ALLOC(alloc); | 715 | struct ocfs2_local_alloc *la = OCFS2_LOCAL_ALLOC(alloc); |
714 | 716 | ||
715 | mlog_entry("total = %u, COUNT = %u, used = %u\n", | 717 | mlog_entry("total = %u, used = %u\n", |
716 | le32_to_cpu(alloc->id1.bitmap1.i_total), | 718 | le32_to_cpu(alloc->id1.bitmap1.i_total), |
717 | ocfs2_local_alloc_count_bits(alloc), | ||
718 | le32_to_cpu(alloc->id1.bitmap1.i_used)); | 719 | le32_to_cpu(alloc->id1.bitmap1.i_used)); |
719 | 720 | ||
720 | if (!alloc->id1.bitmap1.i_total) { | 721 | if (!alloc->id1.bitmap1.i_total) { |
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c index 729259016c18..989ac2718587 100644 --- a/fs/ocfs2/namei.c +++ b/fs/ocfs2/namei.c | |||
@@ -1105,9 +1105,16 @@ static int ocfs2_rename(struct inode *old_dir, | |||
1105 | goto bail; | 1105 | goto bail; |
1106 | } | 1106 | } |
1107 | 1107 | ||
1108 | if (!new_de && new_inode) | 1108 | if (!new_de && new_inode) { |
1109 | mlog(ML_ERROR, "inode %lu does not exist in it's parent " | 1109 | /* |
1110 | "directory!", new_inode->i_ino); | 1110 | * Target was unlinked by another node while we were |
1111 | * waiting to get to ocfs2_rename(). There isn't | ||
1112 | * anything we can do here to help the situation, so | ||
1113 | * bubble up the appropriate error. | ||
1114 | */ | ||
1115 | status = -ENOENT; | ||
1116 | goto bail; | ||
1117 | } | ||
1111 | 1118 | ||
1112 | /* In case we need to overwrite an existing file, we blow it | 1119 | /* In case we need to overwrite an existing file, we blow it |
1113 | * away first */ | 1120 | * away first */ |
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index be562ac3e89c..5ee775420665 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c | |||
@@ -438,14 +438,14 @@ unlock_osb: | |||
438 | } | 438 | } |
439 | 439 | ||
440 | if (!ret) { | 440 | if (!ret) { |
441 | if (!ocfs2_is_hard_readonly(osb)) | ||
442 | ocfs2_set_journal_params(osb); | ||
443 | |||
444 | /* Only save off the new mount options in case of a successful | 441 | /* Only save off the new mount options in case of a successful |
445 | * remount. */ | 442 | * remount. */ |
446 | osb->s_mount_opt = parsed_options.mount_opt; | 443 | osb->s_mount_opt = parsed_options.mount_opt; |
447 | osb->s_atime_quantum = parsed_options.atime_quantum; | 444 | osb->s_atime_quantum = parsed_options.atime_quantum; |
448 | osb->preferred_slot = parsed_options.slot; | 445 | osb->preferred_slot = parsed_options.slot; |
446 | |||
447 | if (!ocfs2_is_hard_readonly(osb)) | ||
448 | ocfs2_set_journal_params(osb); | ||
449 | } | 449 | } |
450 | out: | 450 | out: |
451 | return ret; | 451 | return ret; |
@@ -569,7 +569,7 @@ asmlinkage long sys_fchmod(unsigned int fd, mode_t mode) | |||
569 | dentry = file->f_path.dentry; | 569 | dentry = file->f_path.dentry; |
570 | inode = dentry->d_inode; | 570 | inode = dentry->d_inode; |
571 | 571 | ||
572 | audit_inode(NULL, inode); | 572 | audit_inode(NULL, dentry); |
573 | 573 | ||
574 | err = -EROFS; | 574 | err = -EROFS; |
575 | if (IS_RDONLY(inode)) | 575 | if (IS_RDONLY(inode)) |
@@ -727,7 +727,7 @@ asmlinkage long sys_fchown(unsigned int fd, uid_t user, gid_t group) | |||
727 | goto out; | 727 | goto out; |
728 | 728 | ||
729 | dentry = file->f_path.dentry; | 729 | dentry = file->f_path.dentry; |
730 | audit_inode(NULL, dentry->d_inode); | 730 | audit_inode(NULL, dentry); |
731 | error = chown_common(dentry, user, group); | 731 | error = chown_common(dentry, user, group); |
732 | fput(file); | 732 | fput(file); |
733 | out: | 733 | out: |
@@ -1061,7 +1061,7 @@ asmlinkage long sys_open(const char __user *filename, int flags, int mode) | |||
1061 | prevent_tail_call(ret); | 1061 | prevent_tail_call(ret); |
1062 | return ret; | 1062 | return ret; |
1063 | } | 1063 | } |
1064 | EXPORT_SYMBOL_GPL(sys_open); | 1064 | EXPORT_UNUSED_SYMBOL_GPL(sys_open); /* To be deleted for 2.6.25 */ |
1065 | 1065 | ||
1066 | asmlinkage long sys_openat(int dfd, const char __user *filename, int flags, | 1066 | asmlinkage long sys_openat(int dfd, const char __user *filename, int flags, |
1067 | int mode) | 1067 | int mode) |
diff --git a/fs/pnode.h b/fs/pnode.h index d45bd8ec36bf..f249be2fee7a 100644 --- a/fs/pnode.h +++ b/fs/pnode.h | |||
@@ -22,6 +22,7 @@ | |||
22 | #define CL_COPY_ALL 0x04 | 22 | #define CL_COPY_ALL 0x04 |
23 | #define CL_MAKE_SHARED 0x08 | 23 | #define CL_MAKE_SHARED 0x08 |
24 | #define CL_PROPAGATION 0x10 | 24 | #define CL_PROPAGATION 0x10 |
25 | #define CL_PRIVATE 0x20 | ||
25 | 26 | ||
26 | static inline void set_mnt_shared(struct vfsmount *mnt) | 27 | static inline void set_mnt_shared(struct vfsmount *mnt) |
27 | { | 28 | { |
diff --git a/fs/proc/array.c b/fs/proc/array.c index 27b59f5f3bd1..65c62e1bfd6f 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c | |||
@@ -77,6 +77,7 @@ | |||
77 | #include <linux/cpuset.h> | 77 | #include <linux/cpuset.h> |
78 | #include <linux/rcupdate.h> | 78 | #include <linux/rcupdate.h> |
79 | #include <linux/delayacct.h> | 79 | #include <linux/delayacct.h> |
80 | #include <linux/pid_namespace.h> | ||
80 | 81 | ||
81 | #include <asm/pgtable.h> | 82 | #include <asm/pgtable.h> |
82 | #include <asm/processor.h> | 83 | #include <asm/processor.h> |
@@ -145,8 +146,7 @@ static inline const char *get_task_state(struct task_struct *tsk) | |||
145 | TASK_UNINTERRUPTIBLE | | 146 | TASK_UNINTERRUPTIBLE | |
146 | TASK_STOPPED | | 147 | TASK_STOPPED | |
147 | TASK_TRACED)) | | 148 | TASK_TRACED)) | |
148 | (tsk->exit_state & (EXIT_ZOMBIE | | 149 | tsk->exit_state; |
149 | EXIT_DEAD)); | ||
150 | const char **p = &task_state_array[0]; | 150 | const char **p = &task_state_array[0]; |
151 | 151 | ||
152 | while (state) { | 152 | while (state) { |
@@ -161,8 +161,15 @@ static inline char *task_state(struct task_struct *p, char *buffer) | |||
161 | struct group_info *group_info; | 161 | struct group_info *group_info; |
162 | int g; | 162 | int g; |
163 | struct fdtable *fdt = NULL; | 163 | struct fdtable *fdt = NULL; |
164 | struct pid_namespace *ns; | ||
165 | pid_t ppid, tpid; | ||
164 | 166 | ||
167 | ns = current->nsproxy->pid_ns; | ||
165 | rcu_read_lock(); | 168 | rcu_read_lock(); |
169 | ppid = pid_alive(p) ? | ||
170 | task_tgid_nr_ns(rcu_dereference(p->real_parent), ns) : 0; | ||
171 | tpid = pid_alive(p) && p->ptrace ? | ||
172 | task_ppid_nr_ns(rcu_dereference(p->parent), ns) : 0; | ||
166 | buffer += sprintf(buffer, | 173 | buffer += sprintf(buffer, |
167 | "State:\t%s\n" | 174 | "State:\t%s\n" |
168 | "Tgid:\t%d\n" | 175 | "Tgid:\t%d\n" |
@@ -172,9 +179,9 @@ static inline char *task_state(struct task_struct *p, char *buffer) | |||
172 | "Uid:\t%d\t%d\t%d\t%d\n" | 179 | "Uid:\t%d\t%d\t%d\t%d\n" |
173 | "Gid:\t%d\t%d\t%d\t%d\n", | 180 | "Gid:\t%d\t%d\t%d\t%d\n", |
174 | get_task_state(p), | 181 | get_task_state(p), |
175 | p->tgid, p->pid, | 182 | task_tgid_nr_ns(p, ns), |
176 | pid_alive(p) ? rcu_dereference(p->real_parent)->tgid : 0, | 183 | task_pid_nr_ns(p, ns), |
177 | pid_alive(p) && p->ptrace ? rcu_dereference(p->parent)->pid : 0, | 184 | ppid, tpid, |
178 | p->uid, p->euid, p->suid, p->fsuid, | 185 | p->uid, p->euid, p->suid, p->fsuid, |
179 | p->gid, p->egid, p->sgid, p->fsgid); | 186 | p->gid, p->egid, p->sgid, p->fsgid); |
180 | 187 | ||
@@ -351,7 +358,8 @@ static cputime_t task_utime(struct task_struct *p) | |||
351 | } | 358 | } |
352 | utime = (clock_t)temp; | 359 | utime = (clock_t)temp; |
353 | 360 | ||
354 | return clock_t_to_cputime(utime); | 361 | p->prev_utime = max(p->prev_utime, clock_t_to_cputime(utime)); |
362 | return p->prev_utime; | ||
355 | } | 363 | } |
356 | 364 | ||
357 | static cputime_t task_stime(struct task_struct *p) | 365 | static cputime_t task_stime(struct task_struct *p) |
@@ -366,7 +374,10 @@ static cputime_t task_stime(struct task_struct *p) | |||
366 | stime = nsec_to_clock_t(p->se.sum_exec_runtime) - | 374 | stime = nsec_to_clock_t(p->se.sum_exec_runtime) - |
367 | cputime_to_clock_t(task_utime(p)); | 375 | cputime_to_clock_t(task_utime(p)); |
368 | 376 | ||
369 | return clock_t_to_cputime(stime); | 377 | if (stime >= 0) |
378 | p->prev_stime = max(p->prev_stime, clock_t_to_cputime(stime)); | ||
379 | |||
380 | return p->prev_stime; | ||
370 | } | 381 | } |
371 | #endif | 382 | #endif |
372 | 383 | ||
@@ -394,6 +405,9 @@ static int do_task_stat(struct task_struct *task, char *buffer, int whole) | |||
394 | unsigned long rsslim = 0; | 405 | unsigned long rsslim = 0; |
395 | char tcomm[sizeof(task->comm)]; | 406 | char tcomm[sizeof(task->comm)]; |
396 | unsigned long flags; | 407 | unsigned long flags; |
408 | struct pid_namespace *ns; | ||
409 | |||
410 | ns = current->nsproxy->pid_ns; | ||
397 | 411 | ||
398 | state = *get_task_state(task); | 412 | state = *get_task_state(task); |
399 | vsize = eip = esp = 0; | 413 | vsize = eip = esp = 0; |
@@ -416,7 +430,7 @@ static int do_task_stat(struct task_struct *task, char *buffer, int whole) | |||
416 | struct signal_struct *sig = task->signal; | 430 | struct signal_struct *sig = task->signal; |
417 | 431 | ||
418 | if (sig->tty) { | 432 | if (sig->tty) { |
419 | tty_pgrp = pid_nr(sig->tty->pgrp); | 433 | tty_pgrp = pid_nr_ns(sig->tty->pgrp, ns); |
420 | tty_nr = new_encode_dev(tty_devnum(sig->tty)); | 434 | tty_nr = new_encode_dev(tty_devnum(sig->tty)); |
421 | } | 435 | } |
422 | 436 | ||
@@ -446,12 +460,12 @@ static int do_task_stat(struct task_struct *task, char *buffer, int whole) | |||
446 | maj_flt += sig->maj_flt; | 460 | maj_flt += sig->maj_flt; |
447 | utime = cputime_add(utime, sig->utime); | 461 | utime = cputime_add(utime, sig->utime); |
448 | stime = cputime_add(stime, sig->stime); | 462 | stime = cputime_add(stime, sig->stime); |
449 | gtime += cputime_add(gtime, sig->gtime); | 463 | gtime = cputime_add(gtime, sig->gtime); |
450 | } | 464 | } |
451 | 465 | ||
452 | sid = signal_session(sig); | 466 | sid = task_session_nr_ns(task, ns); |
453 | pgid = process_group(task); | 467 | pgid = task_pgrp_nr_ns(task, ns); |
454 | ppid = rcu_dereference(task->real_parent)->tgid; | 468 | ppid = task_ppid_nr_ns(task, ns); |
455 | 469 | ||
456 | unlock_task_sighand(task, &flags); | 470 | unlock_task_sighand(task, &flags); |
457 | } | 471 | } |
@@ -483,7 +497,7 @@ static int do_task_stat(struct task_struct *task, char *buffer, int whole) | |||
483 | res = sprintf(buffer, "%d (%s) %c %d %d %d %d %d %u %lu \ | 497 | res = sprintf(buffer, "%d (%s) %c %d %d %d %d %d %u %lu \ |
484 | %lu %lu %lu %lu %lu %ld %ld %ld %ld %d 0 %llu %lu %ld %lu %lu %lu %lu %lu \ | 498 | %lu %lu %lu %lu %lu %ld %ld %ld %ld %d 0 %llu %lu %ld %lu %lu %lu %lu %lu \ |
485 | %lu %lu %lu %lu %lu %lu %lu %lu %d %d %u %u %llu %lu %ld\n", | 499 | %lu %lu %lu %lu %lu %lu %lu %lu %d %d %u %u %llu %lu %ld\n", |
486 | task->pid, | 500 | task_pid_nr_ns(task, ns), |
487 | tcomm, | 501 | tcomm, |
488 | state, | 502 | state, |
489 | ppid, | 503 | ppid, |
diff --git a/fs/proc/base.c b/fs/proc/base.c index 4fe74d156416..02a63ac04178 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
@@ -63,16 +63,19 @@ | |||
63 | #include <linux/mm.h> | 63 | #include <linux/mm.h> |
64 | #include <linux/rcupdate.h> | 64 | #include <linux/rcupdate.h> |
65 | #include <linux/kallsyms.h> | 65 | #include <linux/kallsyms.h> |
66 | #include <linux/resource.h> | ||
66 | #include <linux/module.h> | 67 | #include <linux/module.h> |
67 | #include <linux/mount.h> | 68 | #include <linux/mount.h> |
68 | #include <linux/security.h> | 69 | #include <linux/security.h> |
69 | #include <linux/ptrace.h> | 70 | #include <linux/ptrace.h> |
71 | #include <linux/cgroup.h> | ||
70 | #include <linux/cpuset.h> | 72 | #include <linux/cpuset.h> |
71 | #include <linux/audit.h> | 73 | #include <linux/audit.h> |
72 | #include <linux/poll.h> | 74 | #include <linux/poll.h> |
73 | #include <linux/nsproxy.h> | 75 | #include <linux/nsproxy.h> |
74 | #include <linux/oom.h> | 76 | #include <linux/oom.h> |
75 | #include <linux/elf.h> | 77 | #include <linux/elf.h> |
78 | #include <linux/pid_namespace.h> | ||
76 | #include "internal.h" | 79 | #include "internal.h" |
77 | 80 | ||
78 | /* NOTE: | 81 | /* NOTE: |
@@ -301,6 +304,78 @@ static int proc_oom_score(struct task_struct *task, char *buffer) | |||
301 | return sprintf(buffer, "%lu\n", points); | 304 | return sprintf(buffer, "%lu\n", points); |
302 | } | 305 | } |
303 | 306 | ||
307 | struct limit_names { | ||
308 | char *name; | ||
309 | char *unit; | ||
310 | }; | ||
311 | |||
312 | static const struct limit_names lnames[RLIM_NLIMITS] = { | ||
313 | [RLIMIT_CPU] = {"Max cpu time", "ms"}, | ||
314 | [RLIMIT_FSIZE] = {"Max file size", "bytes"}, | ||
315 | [RLIMIT_DATA] = {"Max data size", "bytes"}, | ||
316 | [RLIMIT_STACK] = {"Max stack size", "bytes"}, | ||
317 | [RLIMIT_CORE] = {"Max core file size", "bytes"}, | ||
318 | [RLIMIT_RSS] = {"Max resident set", "bytes"}, | ||
319 | [RLIMIT_NPROC] = {"Max processes", "processes"}, | ||
320 | [RLIMIT_NOFILE] = {"Max open files", "files"}, | ||
321 | [RLIMIT_MEMLOCK] = {"Max locked memory", "bytes"}, | ||
322 | [RLIMIT_AS] = {"Max address space", "bytes"}, | ||
323 | [RLIMIT_LOCKS] = {"Max file locks", "locks"}, | ||
324 | [RLIMIT_SIGPENDING] = {"Max pending signals", "signals"}, | ||
325 | [RLIMIT_MSGQUEUE] = {"Max msgqueue size", "bytes"}, | ||
326 | [RLIMIT_NICE] = {"Max nice priority", NULL}, | ||
327 | [RLIMIT_RTPRIO] = {"Max realtime priority", NULL}, | ||
328 | }; | ||
329 | |||
330 | /* Display limits for a process */ | ||
331 | static int proc_pid_limits(struct task_struct *task, char *buffer) | ||
332 | { | ||
333 | unsigned int i; | ||
334 | int count = 0; | ||
335 | unsigned long flags; | ||
336 | char *bufptr = buffer; | ||
337 | |||
338 | struct rlimit rlim[RLIM_NLIMITS]; | ||
339 | |||
340 | rcu_read_lock(); | ||
341 | if (!lock_task_sighand(task,&flags)) { | ||
342 | rcu_read_unlock(); | ||
343 | return 0; | ||
344 | } | ||
345 | memcpy(rlim, task->signal->rlim, sizeof(struct rlimit) * RLIM_NLIMITS); | ||
346 | unlock_task_sighand(task, &flags); | ||
347 | rcu_read_unlock(); | ||
348 | |||
349 | /* | ||
350 | * print the file header | ||
351 | */ | ||
352 | count += sprintf(&bufptr[count], "%-25s %-20s %-20s %-10s\n", | ||
353 | "Limit", "Soft Limit", "Hard Limit", "Units"); | ||
354 | |||
355 | for (i = 0; i < RLIM_NLIMITS; i++) { | ||
356 | if (rlim[i].rlim_cur == RLIM_INFINITY) | ||
357 | count += sprintf(&bufptr[count], "%-25s %-20s ", | ||
358 | lnames[i].name, "unlimited"); | ||
359 | else | ||
360 | count += sprintf(&bufptr[count], "%-25s %-20lu ", | ||
361 | lnames[i].name, rlim[i].rlim_cur); | ||
362 | |||
363 | if (rlim[i].rlim_max == RLIM_INFINITY) | ||
364 | count += sprintf(&bufptr[count], "%-20s ", "unlimited"); | ||
365 | else | ||
366 | count += sprintf(&bufptr[count], "%-20lu ", | ||
367 | rlim[i].rlim_max); | ||
368 | |||
369 | if (lnames[i].unit) | ||
370 | count += sprintf(&bufptr[count], "%-10s\n", | ||
371 | lnames[i].unit); | ||
372 | else | ||
373 | count += sprintf(&bufptr[count], "\n"); | ||
374 | } | ||
375 | |||
376 | return count; | ||
377 | } | ||
378 | |||
304 | /************************************************************************/ | 379 | /************************************************************************/ |
305 | /* Here the fs part begins */ | 380 | /* Here the fs part begins */ |
306 | /************************************************************************/ | 381 | /************************************************************************/ |
@@ -349,18 +424,21 @@ struct proc_mounts { | |||
349 | static int mounts_open(struct inode *inode, struct file *file) | 424 | static int mounts_open(struct inode *inode, struct file *file) |
350 | { | 425 | { |
351 | struct task_struct *task = get_proc_task(inode); | 426 | struct task_struct *task = get_proc_task(inode); |
427 | struct nsproxy *nsp; | ||
352 | struct mnt_namespace *ns = NULL; | 428 | struct mnt_namespace *ns = NULL; |
353 | struct proc_mounts *p; | 429 | struct proc_mounts *p; |
354 | int ret = -EINVAL; | 430 | int ret = -EINVAL; |
355 | 431 | ||
356 | if (task) { | 432 | if (task) { |
357 | task_lock(task); | 433 | rcu_read_lock(); |
358 | if (task->nsproxy) { | 434 | nsp = task_nsproxy(task); |
359 | ns = task->nsproxy->mnt_ns; | 435 | if (nsp) { |
436 | ns = nsp->mnt_ns; | ||
360 | if (ns) | 437 | if (ns) |
361 | get_mnt_ns(ns); | 438 | get_mnt_ns(ns); |
362 | } | 439 | } |
363 | task_unlock(task); | 440 | rcu_read_unlock(); |
441 | |||
364 | put_task_struct(task); | 442 | put_task_struct(task); |
365 | } | 443 | } |
366 | 444 | ||
@@ -423,16 +501,20 @@ static int mountstats_open(struct inode *inode, struct file *file) | |||
423 | 501 | ||
424 | if (!ret) { | 502 | if (!ret) { |
425 | struct seq_file *m = file->private_data; | 503 | struct seq_file *m = file->private_data; |
504 | struct nsproxy *nsp; | ||
426 | struct mnt_namespace *mnt_ns = NULL; | 505 | struct mnt_namespace *mnt_ns = NULL; |
427 | struct task_struct *task = get_proc_task(inode); | 506 | struct task_struct *task = get_proc_task(inode); |
428 | 507 | ||
429 | if (task) { | 508 | if (task) { |
430 | task_lock(task); | 509 | rcu_read_lock(); |
431 | if (task->nsproxy) | 510 | nsp = task_nsproxy(task); |
432 | mnt_ns = task->nsproxy->mnt_ns; | 511 | if (nsp) { |
433 | if (mnt_ns) | 512 | mnt_ns = nsp->mnt_ns; |
434 | get_mnt_ns(mnt_ns); | 513 | if (mnt_ns) |
435 | task_unlock(task); | 514 | get_mnt_ns(mnt_ns); |
515 | } | ||
516 | rcu_read_unlock(); | ||
517 | |||
436 | put_task_struct(task); | 518 | put_task_struct(task); |
437 | } | 519 | } |
438 | 520 | ||
@@ -1437,7 +1519,7 @@ static int proc_readfd_common(struct file * filp, void * dirent, | |||
1437 | struct dentry *dentry = filp->f_path.dentry; | 1519 | struct dentry *dentry = filp->f_path.dentry; |
1438 | struct inode *inode = dentry->d_inode; | 1520 | struct inode *inode = dentry->d_inode; |
1439 | struct task_struct *p = get_proc_task(inode); | 1521 | struct task_struct *p = get_proc_task(inode); |
1440 | unsigned int fd, tid, ino; | 1522 | unsigned int fd, ino; |
1441 | int retval; | 1523 | int retval; |
1442 | struct files_struct * files; | 1524 | struct files_struct * files; |
1443 | struct fdtable *fdt; | 1525 | struct fdtable *fdt; |
@@ -1446,7 +1528,6 @@ static int proc_readfd_common(struct file * filp, void * dirent, | |||
1446 | if (!p) | 1528 | if (!p) |
1447 | goto out_no_task; | 1529 | goto out_no_task; |
1448 | retval = 0; | 1530 | retval = 0; |
1449 | tid = p->pid; | ||
1450 | 1531 | ||
1451 | fd = filp->f_pos; | 1532 | fd = filp->f_pos; |
1452 | switch (fd) { | 1533 | switch (fd) { |
@@ -1681,7 +1762,6 @@ static int proc_pident_readdir(struct file *filp, | |||
1681 | const struct pid_entry *ents, unsigned int nents) | 1762 | const struct pid_entry *ents, unsigned int nents) |
1682 | { | 1763 | { |
1683 | int i; | 1764 | int i; |
1684 | int pid; | ||
1685 | struct dentry *dentry = filp->f_path.dentry; | 1765 | struct dentry *dentry = filp->f_path.dentry; |
1686 | struct inode *inode = dentry->d_inode; | 1766 | struct inode *inode = dentry->d_inode; |
1687 | struct task_struct *task = get_proc_task(inode); | 1767 | struct task_struct *task = get_proc_task(inode); |
@@ -1694,7 +1774,6 @@ static int proc_pident_readdir(struct file *filp, | |||
1694 | goto out_no_task; | 1774 | goto out_no_task; |
1695 | 1775 | ||
1696 | ret = 0; | 1776 | ret = 0; |
1697 | pid = task->pid; | ||
1698 | i = filp->f_pos; | 1777 | i = filp->f_pos; |
1699 | switch (i) { | 1778 | switch (i) { |
1700 | case 0: | 1779 | case 0: |
@@ -1928,14 +2007,14 @@ static int proc_self_readlink(struct dentry *dentry, char __user *buffer, | |||
1928 | int buflen) | 2007 | int buflen) |
1929 | { | 2008 | { |
1930 | char tmp[PROC_NUMBUF]; | 2009 | char tmp[PROC_NUMBUF]; |
1931 | sprintf(tmp, "%d", current->tgid); | 2010 | sprintf(tmp, "%d", task_tgid_vnr(current)); |
1932 | return vfs_readlink(dentry,buffer,buflen,tmp); | 2011 | return vfs_readlink(dentry,buffer,buflen,tmp); |
1933 | } | 2012 | } |
1934 | 2013 | ||
1935 | static void *proc_self_follow_link(struct dentry *dentry, struct nameidata *nd) | 2014 | static void *proc_self_follow_link(struct dentry *dentry, struct nameidata *nd) |
1936 | { | 2015 | { |
1937 | char tmp[PROC_NUMBUF]; | 2016 | char tmp[PROC_NUMBUF]; |
1938 | sprintf(tmp, "%d", current->tgid); | 2017 | sprintf(tmp, "%d", task_tgid_vnr(current)); |
1939 | return ERR_PTR(vfs_follow_link(nd,tmp)); | 2018 | return ERR_PTR(vfs_follow_link(nd,tmp)); |
1940 | } | 2019 | } |
1941 | 2020 | ||
@@ -2101,6 +2180,7 @@ static const struct pid_entry tgid_base_stuff[] = { | |||
2101 | REG("environ", S_IRUSR, environ), | 2180 | REG("environ", S_IRUSR, environ), |
2102 | INF("auxv", S_IRUSR, pid_auxv), | 2181 | INF("auxv", S_IRUSR, pid_auxv), |
2103 | INF("status", S_IRUGO, pid_status), | 2182 | INF("status", S_IRUGO, pid_status), |
2183 | INF("limits", S_IRUSR, pid_limits), | ||
2104 | #ifdef CONFIG_SCHED_DEBUG | 2184 | #ifdef CONFIG_SCHED_DEBUG |
2105 | REG("sched", S_IRUGO|S_IWUSR, pid_sched), | 2185 | REG("sched", S_IRUGO|S_IWUSR, pid_sched), |
2106 | #endif | 2186 | #endif |
@@ -2130,9 +2210,12 @@ static const struct pid_entry tgid_base_stuff[] = { | |||
2130 | #ifdef CONFIG_SCHEDSTATS | 2210 | #ifdef CONFIG_SCHEDSTATS |
2131 | INF("schedstat", S_IRUGO, pid_schedstat), | 2211 | INF("schedstat", S_IRUGO, pid_schedstat), |
2132 | #endif | 2212 | #endif |
2133 | #ifdef CONFIG_CPUSETS | 2213 | #ifdef CONFIG_PROC_PID_CPUSET |
2134 | REG("cpuset", S_IRUGO, cpuset), | 2214 | REG("cpuset", S_IRUGO, cpuset), |
2135 | #endif | 2215 | #endif |
2216 | #ifdef CONFIG_CGROUPS | ||
2217 | REG("cgroup", S_IRUGO, cgroup), | ||
2218 | #endif | ||
2136 | INF("oom_score", S_IRUGO, oom_score), | 2219 | INF("oom_score", S_IRUGO, oom_score), |
2137 | REG("oom_adj", S_IRUGO|S_IWUSR, oom_adjust), | 2220 | REG("oom_adj", S_IRUGO|S_IWUSR, oom_adjust), |
2138 | #ifdef CONFIG_AUDITSYSCALL | 2221 | #ifdef CONFIG_AUDITSYSCALL |
@@ -2172,48 +2255,27 @@ static const struct inode_operations proc_tgid_base_inode_operations = { | |||
2172 | .setattr = proc_setattr, | 2255 | .setattr = proc_setattr, |
2173 | }; | 2256 | }; |
2174 | 2257 | ||
2175 | /** | 2258 | static void proc_flush_task_mnt(struct vfsmount *mnt, pid_t pid, pid_t tgid) |
2176 | * proc_flush_task - Remove dcache entries for @task from the /proc dcache. | ||
2177 | * | ||
2178 | * @task: task that should be flushed. | ||
2179 | * | ||
2180 | * Looks in the dcache for | ||
2181 | * /proc/@pid | ||
2182 | * /proc/@tgid/task/@pid | ||
2183 | * if either directory is present flushes it and all of it'ts children | ||
2184 | * from the dcache. | ||
2185 | * | ||
2186 | * It is safe and reasonable to cache /proc entries for a task until | ||
2187 | * that task exits. After that they just clog up the dcache with | ||
2188 | * useless entries, possibly causing useful dcache entries to be | ||
2189 | * flushed instead. This routine is proved to flush those useless | ||
2190 | * dcache entries at process exit time. | ||
2191 | * | ||
2192 | * NOTE: This routine is just an optimization so it does not guarantee | ||
2193 | * that no dcache entries will exist at process exit time it | ||
2194 | * just makes it very unlikely that any will persist. | ||
2195 | */ | ||
2196 | void proc_flush_task(struct task_struct *task) | ||
2197 | { | 2259 | { |
2198 | struct dentry *dentry, *leader, *dir; | 2260 | struct dentry *dentry, *leader, *dir; |
2199 | char buf[PROC_NUMBUF]; | 2261 | char buf[PROC_NUMBUF]; |
2200 | struct qstr name; | 2262 | struct qstr name; |
2201 | 2263 | ||
2202 | name.name = buf; | 2264 | name.name = buf; |
2203 | name.len = snprintf(buf, sizeof(buf), "%d", task->pid); | 2265 | name.len = snprintf(buf, sizeof(buf), "%d", pid); |
2204 | dentry = d_hash_and_lookup(proc_mnt->mnt_root, &name); | 2266 | dentry = d_hash_and_lookup(mnt->mnt_root, &name); |
2205 | if (dentry) { | 2267 | if (dentry) { |
2206 | shrink_dcache_parent(dentry); | 2268 | shrink_dcache_parent(dentry); |
2207 | d_drop(dentry); | 2269 | d_drop(dentry); |
2208 | dput(dentry); | 2270 | dput(dentry); |
2209 | } | 2271 | } |
2210 | 2272 | ||
2211 | if (thread_group_leader(task)) | 2273 | if (tgid == 0) |
2212 | goto out; | 2274 | goto out; |
2213 | 2275 | ||
2214 | name.name = buf; | 2276 | name.name = buf; |
2215 | name.len = snprintf(buf, sizeof(buf), "%d", task->tgid); | 2277 | name.len = snprintf(buf, sizeof(buf), "%d", tgid); |
2216 | leader = d_hash_and_lookup(proc_mnt->mnt_root, &name); | 2278 | leader = d_hash_and_lookup(mnt->mnt_root, &name); |
2217 | if (!leader) | 2279 | if (!leader) |
2218 | goto out; | 2280 | goto out; |
2219 | 2281 | ||
@@ -2224,7 +2286,7 @@ void proc_flush_task(struct task_struct *task) | |||
2224 | goto out_put_leader; | 2286 | goto out_put_leader; |
2225 | 2287 | ||
2226 | name.name = buf; | 2288 | name.name = buf; |
2227 | name.len = snprintf(buf, sizeof(buf), "%d", task->pid); | 2289 | name.len = snprintf(buf, sizeof(buf), "%d", pid); |
2228 | dentry = d_hash_and_lookup(dir, &name); | 2290 | dentry = d_hash_and_lookup(dir, &name); |
2229 | if (dentry) { | 2291 | if (dentry) { |
2230 | shrink_dcache_parent(dentry); | 2292 | shrink_dcache_parent(dentry); |
@@ -2239,6 +2301,52 @@ out: | |||
2239 | return; | 2301 | return; |
2240 | } | 2302 | } |
2241 | 2303 | ||
2304 | /** | ||
2305 | * proc_flush_task - Remove dcache entries for @task from the /proc dcache. | ||
2306 | * @task: task that should be flushed. | ||
2307 | * | ||
2308 | * When flushing dentries from proc, one needs to flush them from global | ||
2309 | * proc (proc_mnt) and from all the namespaces' procs this task was seen | ||
2310 | * in. This call is supposed to do all of this job. | ||
2311 | * | ||
2312 | * Looks in the dcache for | ||
2313 | * /proc/@pid | ||
2314 | * /proc/@tgid/task/@pid | ||
2315 | * if either directory is present flushes it and all of it'ts children | ||
2316 | * from the dcache. | ||
2317 | * | ||
2318 | * It is safe and reasonable to cache /proc entries for a task until | ||
2319 | * that task exits. After that they just clog up the dcache with | ||
2320 | * useless entries, possibly causing useful dcache entries to be | ||
2321 | * flushed instead. This routine is proved to flush those useless | ||
2322 | * dcache entries at process exit time. | ||
2323 | * | ||
2324 | * NOTE: This routine is just an optimization so it does not guarantee | ||
2325 | * that no dcache entries will exist at process exit time it | ||
2326 | * just makes it very unlikely that any will persist. | ||
2327 | */ | ||
2328 | |||
2329 | void proc_flush_task(struct task_struct *task) | ||
2330 | { | ||
2331 | int i; | ||
2332 | struct pid *pid, *tgid = NULL; | ||
2333 | struct upid *upid; | ||
2334 | |||
2335 | pid = task_pid(task); | ||
2336 | if (thread_group_leader(task)) | ||
2337 | tgid = task_tgid(task); | ||
2338 | |||
2339 | for (i = 0; i <= pid->level; i++) { | ||
2340 | upid = &pid->numbers[i]; | ||
2341 | proc_flush_task_mnt(upid->ns->proc_mnt, upid->nr, | ||
2342 | tgid ? tgid->numbers[i].nr : 0); | ||
2343 | } | ||
2344 | |||
2345 | upid = &pid->numbers[pid->level]; | ||
2346 | if (upid->nr == 1) | ||
2347 | pid_ns_release_proc(upid->ns); | ||
2348 | } | ||
2349 | |||
2242 | static struct dentry *proc_pid_instantiate(struct inode *dir, | 2350 | static struct dentry *proc_pid_instantiate(struct inode *dir, |
2243 | struct dentry * dentry, | 2351 | struct dentry * dentry, |
2244 | struct task_struct *task, const void *ptr) | 2352 | struct task_struct *task, const void *ptr) |
@@ -2274,6 +2382,7 @@ struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, struct | |||
2274 | struct dentry *result = ERR_PTR(-ENOENT); | 2382 | struct dentry *result = ERR_PTR(-ENOENT); |
2275 | struct task_struct *task; | 2383 | struct task_struct *task; |
2276 | unsigned tgid; | 2384 | unsigned tgid; |
2385 | struct pid_namespace *ns; | ||
2277 | 2386 | ||
2278 | result = proc_base_lookup(dir, dentry); | 2387 | result = proc_base_lookup(dir, dentry); |
2279 | if (!IS_ERR(result) || PTR_ERR(result) != -ENOENT) | 2388 | if (!IS_ERR(result) || PTR_ERR(result) != -ENOENT) |
@@ -2283,8 +2392,9 @@ struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, struct | |||
2283 | if (tgid == ~0U) | 2392 | if (tgid == ~0U) |
2284 | goto out; | 2393 | goto out; |
2285 | 2394 | ||
2395 | ns = dentry->d_sb->s_fs_info; | ||
2286 | rcu_read_lock(); | 2396 | rcu_read_lock(); |
2287 | task = find_task_by_pid(tgid); | 2397 | task = find_task_by_pid_ns(tgid, ns); |
2288 | if (task) | 2398 | if (task) |
2289 | get_task_struct(task); | 2399 | get_task_struct(task); |
2290 | rcu_read_unlock(); | 2400 | rcu_read_unlock(); |
@@ -2301,18 +2411,23 @@ out: | |||
2301 | * Find the first task with tgid >= tgid | 2411 | * Find the first task with tgid >= tgid |
2302 | * | 2412 | * |
2303 | */ | 2413 | */ |
2304 | static struct task_struct *next_tgid(unsigned int tgid) | 2414 | struct tgid_iter { |
2305 | { | 2415 | unsigned int tgid; |
2306 | struct task_struct *task; | 2416 | struct task_struct *task; |
2417 | }; | ||
2418 | static struct tgid_iter next_tgid(struct pid_namespace *ns, struct tgid_iter iter) | ||
2419 | { | ||
2307 | struct pid *pid; | 2420 | struct pid *pid; |
2308 | 2421 | ||
2422 | if (iter.task) | ||
2423 | put_task_struct(iter.task); | ||
2309 | rcu_read_lock(); | 2424 | rcu_read_lock(); |
2310 | retry: | 2425 | retry: |
2311 | task = NULL; | 2426 | iter.task = NULL; |
2312 | pid = find_ge_pid(tgid); | 2427 | pid = find_ge_pid(iter.tgid, ns); |
2313 | if (pid) { | 2428 | if (pid) { |
2314 | tgid = pid->nr + 1; | 2429 | iter.tgid = pid_nr_ns(pid, ns); |
2315 | task = pid_task(pid, PIDTYPE_PID); | 2430 | iter.task = pid_task(pid, PIDTYPE_PID); |
2316 | /* What we to know is if the pid we have find is the | 2431 | /* What we to know is if the pid we have find is the |
2317 | * pid of a thread_group_leader. Testing for task | 2432 | * pid of a thread_group_leader. Testing for task |
2318 | * being a thread_group_leader is the obvious thing | 2433 | * being a thread_group_leader is the obvious thing |
@@ -2325,23 +2440,25 @@ retry: | |||
2325 | * found doesn't happen to be a thread group leader. | 2440 | * found doesn't happen to be a thread group leader. |
2326 | * As we don't care in the case of readdir. | 2441 | * As we don't care in the case of readdir. |
2327 | */ | 2442 | */ |
2328 | if (!task || !has_group_leader_pid(task)) | 2443 | if (!iter.task || !has_group_leader_pid(iter.task)) { |
2444 | iter.tgid += 1; | ||
2329 | goto retry; | 2445 | goto retry; |
2330 | get_task_struct(task); | 2446 | } |
2447 | get_task_struct(iter.task); | ||
2331 | } | 2448 | } |
2332 | rcu_read_unlock(); | 2449 | rcu_read_unlock(); |
2333 | return task; | 2450 | return iter; |
2334 | } | 2451 | } |
2335 | 2452 | ||
2336 | #define TGID_OFFSET (FIRST_PROCESS_ENTRY + ARRAY_SIZE(proc_base_stuff)) | 2453 | #define TGID_OFFSET (FIRST_PROCESS_ENTRY + ARRAY_SIZE(proc_base_stuff)) |
2337 | 2454 | ||
2338 | static int proc_pid_fill_cache(struct file *filp, void *dirent, filldir_t filldir, | 2455 | static int proc_pid_fill_cache(struct file *filp, void *dirent, filldir_t filldir, |
2339 | struct task_struct *task, int tgid) | 2456 | struct tgid_iter iter) |
2340 | { | 2457 | { |
2341 | char name[PROC_NUMBUF]; | 2458 | char name[PROC_NUMBUF]; |
2342 | int len = snprintf(name, sizeof(name), "%d", tgid); | 2459 | int len = snprintf(name, sizeof(name), "%d", iter.tgid); |
2343 | return proc_fill_cache(filp, dirent, filldir, name, len, | 2460 | return proc_fill_cache(filp, dirent, filldir, name, len, |
2344 | proc_pid_instantiate, task, NULL); | 2461 | proc_pid_instantiate, iter.task, NULL); |
2345 | } | 2462 | } |
2346 | 2463 | ||
2347 | /* for the /proc/ directory itself, after non-process stuff has been done */ | 2464 | /* for the /proc/ directory itself, after non-process stuff has been done */ |
@@ -2349,8 +2466,8 @@ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir) | |||
2349 | { | 2466 | { |
2350 | unsigned int nr = filp->f_pos - FIRST_PROCESS_ENTRY; | 2467 | unsigned int nr = filp->f_pos - FIRST_PROCESS_ENTRY; |
2351 | struct task_struct *reaper = get_proc_task(filp->f_path.dentry->d_inode); | 2468 | struct task_struct *reaper = get_proc_task(filp->f_path.dentry->d_inode); |
2352 | struct task_struct *task; | 2469 | struct tgid_iter iter; |
2353 | int tgid; | 2470 | struct pid_namespace *ns; |
2354 | 2471 | ||
2355 | if (!reaper) | 2472 | if (!reaper) |
2356 | goto out_no_task; | 2473 | goto out_no_task; |
@@ -2361,14 +2478,15 @@ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir) | |||
2361 | goto out; | 2478 | goto out; |
2362 | } | 2479 | } |
2363 | 2480 | ||
2364 | tgid = filp->f_pos - TGID_OFFSET; | 2481 | ns = filp->f_dentry->d_sb->s_fs_info; |
2365 | for (task = next_tgid(tgid); | 2482 | iter.task = NULL; |
2366 | task; | 2483 | iter.tgid = filp->f_pos - TGID_OFFSET; |
2367 | put_task_struct(task), task = next_tgid(tgid + 1)) { | 2484 | for (iter = next_tgid(ns, iter); |
2368 | tgid = task->pid; | 2485 | iter.task; |
2369 | filp->f_pos = tgid + TGID_OFFSET; | 2486 | iter.tgid += 1, iter = next_tgid(ns, iter)) { |
2370 | if (proc_pid_fill_cache(filp, dirent, filldir, task, tgid) < 0) { | 2487 | filp->f_pos = iter.tgid + TGID_OFFSET; |
2371 | put_task_struct(task); | 2488 | if (proc_pid_fill_cache(filp, dirent, filldir, iter) < 0) { |
2489 | put_task_struct(iter.task); | ||
2372 | goto out; | 2490 | goto out; |
2373 | } | 2491 | } |
2374 | } | 2492 | } |
@@ -2388,6 +2506,7 @@ static const struct pid_entry tid_base_stuff[] = { | |||
2388 | REG("environ", S_IRUSR, environ), | 2506 | REG("environ", S_IRUSR, environ), |
2389 | INF("auxv", S_IRUSR, pid_auxv), | 2507 | INF("auxv", S_IRUSR, pid_auxv), |
2390 | INF("status", S_IRUGO, pid_status), | 2508 | INF("status", S_IRUGO, pid_status), |
2509 | INF("limits", S_IRUSR, pid_limits), | ||
2391 | #ifdef CONFIG_SCHED_DEBUG | 2510 | #ifdef CONFIG_SCHED_DEBUG |
2392 | REG("sched", S_IRUGO|S_IWUSR, pid_sched), | 2511 | REG("sched", S_IRUGO|S_IWUSR, pid_sched), |
2393 | #endif | 2512 | #endif |
@@ -2416,9 +2535,12 @@ static const struct pid_entry tid_base_stuff[] = { | |||
2416 | #ifdef CONFIG_SCHEDSTATS | 2535 | #ifdef CONFIG_SCHEDSTATS |
2417 | INF("schedstat", S_IRUGO, pid_schedstat), | 2536 | INF("schedstat", S_IRUGO, pid_schedstat), |
2418 | #endif | 2537 | #endif |
2419 | #ifdef CONFIG_CPUSETS | 2538 | #ifdef CONFIG_PROC_PID_CPUSET |
2420 | REG("cpuset", S_IRUGO, cpuset), | 2539 | REG("cpuset", S_IRUGO, cpuset), |
2421 | #endif | 2540 | #endif |
2541 | #ifdef CONFIG_CGROUPS | ||
2542 | REG("cgroup", S_IRUGO, cgroup), | ||
2543 | #endif | ||
2422 | INF("oom_score", S_IRUGO, oom_score), | 2544 | INF("oom_score", S_IRUGO, oom_score), |
2423 | REG("oom_adj", S_IRUGO|S_IWUSR, oom_adjust), | 2545 | REG("oom_adj", S_IRUGO|S_IWUSR, oom_adjust), |
2424 | #ifdef CONFIG_AUDITSYSCALL | 2546 | #ifdef CONFIG_AUDITSYSCALL |
@@ -2486,6 +2608,7 @@ static struct dentry *proc_task_lookup(struct inode *dir, struct dentry * dentry | |||
2486 | struct task_struct *task; | 2608 | struct task_struct *task; |
2487 | struct task_struct *leader = get_proc_task(dir); | 2609 | struct task_struct *leader = get_proc_task(dir); |
2488 | unsigned tid; | 2610 | unsigned tid; |
2611 | struct pid_namespace *ns; | ||
2489 | 2612 | ||
2490 | if (!leader) | 2613 | if (!leader) |
2491 | goto out_no_task; | 2614 | goto out_no_task; |
@@ -2494,14 +2617,15 @@ static struct dentry *proc_task_lookup(struct inode *dir, struct dentry * dentry | |||
2494 | if (tid == ~0U) | 2617 | if (tid == ~0U) |
2495 | goto out; | 2618 | goto out; |
2496 | 2619 | ||
2620 | ns = dentry->d_sb->s_fs_info; | ||
2497 | rcu_read_lock(); | 2621 | rcu_read_lock(); |
2498 | task = find_task_by_pid(tid); | 2622 | task = find_task_by_pid_ns(tid, ns); |
2499 | if (task) | 2623 | if (task) |
2500 | get_task_struct(task); | 2624 | get_task_struct(task); |
2501 | rcu_read_unlock(); | 2625 | rcu_read_unlock(); |
2502 | if (!task) | 2626 | if (!task) |
2503 | goto out; | 2627 | goto out; |
2504 | if (leader->tgid != task->tgid) | 2628 | if (!same_thread_group(leader, task)) |
2505 | goto out_drop_task; | 2629 | goto out_drop_task; |
2506 | 2630 | ||
2507 | result = proc_task_instantiate(dir, dentry, task, NULL); | 2631 | result = proc_task_instantiate(dir, dentry, task, NULL); |
@@ -2526,14 +2650,14 @@ out_no_task: | |||
2526 | * threads past it. | 2650 | * threads past it. |
2527 | */ | 2651 | */ |
2528 | static struct task_struct *first_tid(struct task_struct *leader, | 2652 | static struct task_struct *first_tid(struct task_struct *leader, |
2529 | int tid, int nr) | 2653 | int tid, int nr, struct pid_namespace *ns) |
2530 | { | 2654 | { |
2531 | struct task_struct *pos; | 2655 | struct task_struct *pos; |
2532 | 2656 | ||
2533 | rcu_read_lock(); | 2657 | rcu_read_lock(); |
2534 | /* Attempt to start with the pid of a thread */ | 2658 | /* Attempt to start with the pid of a thread */ |
2535 | if (tid && (nr > 0)) { | 2659 | if (tid && (nr > 0)) { |
2536 | pos = find_task_by_pid(tid); | 2660 | pos = find_task_by_pid_ns(tid, ns); |
2537 | if (pos && (pos->group_leader == leader)) | 2661 | if (pos && (pos->group_leader == leader)) |
2538 | goto found; | 2662 | goto found; |
2539 | } | 2663 | } |
@@ -2602,6 +2726,7 @@ static int proc_task_readdir(struct file * filp, void * dirent, filldir_t filldi | |||
2602 | ino_t ino; | 2726 | ino_t ino; |
2603 | int tid; | 2727 | int tid; |
2604 | unsigned long pos = filp->f_pos; /* avoiding "long long" filp->f_pos */ | 2728 | unsigned long pos = filp->f_pos; /* avoiding "long long" filp->f_pos */ |
2729 | struct pid_namespace *ns; | ||
2605 | 2730 | ||
2606 | task = get_proc_task(inode); | 2731 | task = get_proc_task(inode); |
2607 | if (!task) | 2732 | if (!task) |
@@ -2635,12 +2760,13 @@ static int proc_task_readdir(struct file * filp, void * dirent, filldir_t filldi | |||
2635 | /* f_version caches the tgid value that the last readdir call couldn't | 2760 | /* f_version caches the tgid value that the last readdir call couldn't |
2636 | * return. lseek aka telldir automagically resets f_version to 0. | 2761 | * return. lseek aka telldir automagically resets f_version to 0. |
2637 | */ | 2762 | */ |
2763 | ns = filp->f_dentry->d_sb->s_fs_info; | ||
2638 | tid = (int)filp->f_version; | 2764 | tid = (int)filp->f_version; |
2639 | filp->f_version = 0; | 2765 | filp->f_version = 0; |
2640 | for (task = first_tid(leader, tid, pos - 2); | 2766 | for (task = first_tid(leader, tid, pos - 2, ns); |
2641 | task; | 2767 | task; |
2642 | task = next_tid(task), pos++) { | 2768 | task = next_tid(task), pos++) { |
2643 | tid = task->pid; | 2769 | tid = task_pid_nr_ns(task, ns); |
2644 | if (proc_task_fill_cache(filp, dirent, filldir, task, tid) < 0) { | 2770 | if (proc_task_fill_cache(filp, dirent, filldir, task, tid) < 0) { |
2645 | /* returning this tgid failed, save it as the first | 2771 | /* returning this tgid failed, save it as the first |
2646 | * pid for the next readir call */ | 2772 | * pid for the next readir call */ |
diff --git a/fs/proc/generic.c b/fs/proc/generic.c index 1bdb62435758..8d49838e5554 100644 --- a/fs/proc/generic.c +++ b/fs/proc/generic.c | |||
@@ -374,9 +374,16 @@ static int proc_delete_dentry(struct dentry * dentry) | |||
374 | return 1; | 374 | return 1; |
375 | } | 375 | } |
376 | 376 | ||
377 | static int proc_revalidate_dentry(struct dentry *dentry, struct nameidata *nd) | ||
378 | { | ||
379 | d_drop(dentry); | ||
380 | return 0; | ||
381 | } | ||
382 | |||
377 | static struct dentry_operations proc_dentry_operations = | 383 | static struct dentry_operations proc_dentry_operations = |
378 | { | 384 | { |
379 | .d_delete = proc_delete_dentry, | 385 | .d_delete = proc_delete_dentry, |
386 | .d_revalidate = proc_revalidate_dentry, | ||
380 | }; | 387 | }; |
381 | 388 | ||
382 | /* | 389 | /* |
@@ -397,8 +404,11 @@ struct dentry *proc_lookup(struct inode * dir, struct dentry *dentry, struct nam | |||
397 | if (de->namelen != dentry->d_name.len) | 404 | if (de->namelen != dentry->d_name.len) |
398 | continue; | 405 | continue; |
399 | if (!memcmp(dentry->d_name.name, de->name, de->namelen)) { | 406 | if (!memcmp(dentry->d_name.name, de->name, de->namelen)) { |
400 | unsigned int ino = de->low_ino; | 407 | unsigned int ino; |
401 | 408 | ||
409 | if (de->shadow_proc) | ||
410 | de = de->shadow_proc(current, de); | ||
411 | ino = de->low_ino; | ||
402 | de_get(de); | 412 | de_get(de); |
403 | spin_unlock(&proc_subdir_lock); | 413 | spin_unlock(&proc_subdir_lock); |
404 | error = -EINVAL; | 414 | error = -EINVAL; |
@@ -555,36 +565,6 @@ static int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp | |||
555 | return 0; | 565 | return 0; |
556 | } | 566 | } |
557 | 567 | ||
558 | /* | ||
559 | * Kill an inode that got unregistered.. | ||
560 | */ | ||
561 | static void proc_kill_inodes(struct proc_dir_entry *de) | ||
562 | { | ||
563 | struct list_head *p; | ||
564 | struct super_block *sb = proc_mnt->mnt_sb; | ||
565 | |||
566 | /* | ||
567 | * Actually it's a partial revoke(). | ||
568 | */ | ||
569 | file_list_lock(); | ||
570 | list_for_each(p, &sb->s_files) { | ||
571 | struct file * filp = list_entry(p, struct file, f_u.fu_list); | ||
572 | struct dentry * dentry = filp->f_path.dentry; | ||
573 | struct inode * inode; | ||
574 | const struct file_operations *fops; | ||
575 | |||
576 | if (dentry->d_op != &proc_dentry_operations) | ||
577 | continue; | ||
578 | inode = dentry->d_inode; | ||
579 | if (PDE(inode) != de) | ||
580 | continue; | ||
581 | fops = filp->f_op; | ||
582 | filp->f_op = NULL; | ||
583 | fops_put(fops); | ||
584 | } | ||
585 | file_list_unlock(); | ||
586 | } | ||
587 | |||
588 | static struct proc_dir_entry *proc_create(struct proc_dir_entry **parent, | 568 | static struct proc_dir_entry *proc_create(struct proc_dir_entry **parent, |
589 | const char *name, | 569 | const char *name, |
590 | mode_t mode, | 570 | mode_t mode, |
@@ -615,6 +595,7 @@ static struct proc_dir_entry *proc_create(struct proc_dir_entry **parent, | |||
615 | ent->namelen = len; | 595 | ent->namelen = len; |
616 | ent->mode = mode; | 596 | ent->mode = mode; |
617 | ent->nlink = nlink; | 597 | ent->nlink = nlink; |
598 | atomic_set(&ent->count, 1); | ||
618 | ent->pde_users = 0; | 599 | ent->pde_users = 0; |
619 | spin_lock_init(&ent->pde_unload_lock); | 600 | spin_lock_init(&ent->pde_unload_lock); |
620 | ent->pde_unload_completion = NULL; | 601 | ent->pde_unload_completion = NULL; |
@@ -712,7 +693,6 @@ void free_proc_entry(struct proc_dir_entry *de) | |||
712 | 693 | ||
713 | /* | 694 | /* |
714 | * Remove a /proc entry and free it if it's not currently in use. | 695 | * Remove a /proc entry and free it if it's not currently in use. |
715 | * If it is in use, we set the 'deleted' flag. | ||
716 | */ | 696 | */ |
717 | void remove_proc_entry(const char *name, struct proc_dir_entry *parent) | 697 | void remove_proc_entry(const char *name, struct proc_dir_entry *parent) |
718 | { | 698 | { |
@@ -759,17 +739,10 @@ void remove_proc_entry(const char *name, struct proc_dir_entry *parent) | |||
759 | continue_removing: | 739 | continue_removing: |
760 | if (S_ISDIR(de->mode)) | 740 | if (S_ISDIR(de->mode)) |
761 | parent->nlink--; | 741 | parent->nlink--; |
762 | if (!S_ISREG(de->mode)) | ||
763 | proc_kill_inodes(de); | ||
764 | de->nlink = 0; | 742 | de->nlink = 0; |
765 | WARN_ON(de->subdir); | 743 | WARN_ON(de->subdir); |
766 | if (!atomic_read(&de->count)) | 744 | if (atomic_dec_and_test(&de->count)) |
767 | free_proc_entry(de); | 745 | free_proc_entry(de); |
768 | else { | ||
769 | de->deleted = 1; | ||
770 | printk("remove_proc_entry: %s/%s busy, count=%d\n", | ||
771 | parent->name, de->name, atomic_read(&de->count)); | ||
772 | } | ||
773 | break; | 746 | break; |
774 | } | 747 | } |
775 | spin_unlock(&proc_subdir_lock); | 748 | spin_unlock(&proc_subdir_lock); |
diff --git a/fs/proc/inode.c b/fs/proc/inode.c index 99ca00485fc3..1a551d92e1d8 100644 --- a/fs/proc/inode.c +++ b/fs/proc/inode.c | |||
@@ -43,13 +43,8 @@ void de_put(struct proc_dir_entry *de) | |||
43 | return; | 43 | return; |
44 | } | 44 | } |
45 | 45 | ||
46 | if (atomic_dec_and_test(&de->count)) { | 46 | if (atomic_dec_and_test(&de->count)) |
47 | if (de->deleted) { | 47 | free_proc_entry(de); |
48 | printk("de_put: deferred delete of %s\n", | ||
49 | de->name); | ||
50 | free_proc_entry(de); | ||
51 | } | ||
52 | } | ||
53 | unlock_kernel(); | 48 | unlock_kernel(); |
54 | } | 49 | } |
55 | } | 50 | } |
@@ -448,7 +443,7 @@ out_mod: | |||
448 | return NULL; | 443 | return NULL; |
449 | } | 444 | } |
450 | 445 | ||
451 | int proc_fill_super(struct super_block *s, void *data, int silent) | 446 | int proc_fill_super(struct super_block *s) |
452 | { | 447 | { |
453 | struct inode * root_inode; | 448 | struct inode * root_inode; |
454 | 449 | ||
diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c index d6dc72c78bc1..e0d064e9764e 100644 --- a/fs/proc/proc_misc.c +++ b/fs/proc/proc_misc.c | |||
@@ -91,7 +91,8 @@ static int loadavg_read_proc(char *page, char **start, off_t off, | |||
91 | LOAD_INT(a), LOAD_FRAC(a), | 91 | LOAD_INT(a), LOAD_FRAC(a), |
92 | LOAD_INT(b), LOAD_FRAC(b), | 92 | LOAD_INT(b), LOAD_FRAC(b), |
93 | LOAD_INT(c), LOAD_FRAC(c), | 93 | LOAD_INT(c), LOAD_FRAC(c), |
94 | nr_running(), nr_threads, current->nsproxy->pid_ns->last_pid); | 94 | nr_running(), nr_threads, |
95 | task_active_pid_ns(current)->last_pid); | ||
95 | return proc_calc_metrics(page, start, off, count, eof, len); | 96 | return proc_calc_metrics(page, start, off, count, eof, len); |
96 | } | 97 | } |
97 | 98 | ||
diff --git a/fs/proc/proc_net.c b/fs/proc/proc_net.c index 2e91fb756e9a..0afe21ee0607 100644 --- a/fs/proc/proc_net.c +++ b/fs/proc/proc_net.c | |||
@@ -26,13 +26,6 @@ | |||
26 | #include "internal.h" | 26 | #include "internal.h" |
27 | 27 | ||
28 | 28 | ||
29 | struct proc_dir_entry *proc_net_create(struct net *net, | ||
30 | const char *name, mode_t mode, get_info_t *get_info) | ||
31 | { | ||
32 | return create_proc_info_entry(name,mode, net->proc_net, get_info); | ||
33 | } | ||
34 | EXPORT_SYMBOL_GPL(proc_net_create); | ||
35 | |||
36 | struct proc_dir_entry *proc_net_fops_create(struct net *net, | 29 | struct proc_dir_entry *proc_net_fops_create(struct net *net, |
37 | const char *name, mode_t mode, const struct file_operations *fops) | 30 | const char *name, mode_t mode, const struct file_operations *fops) |
38 | { | 31 | { |
@@ -57,89 +50,14 @@ struct net *get_proc_net(const struct inode *inode) | |||
57 | } | 50 | } |
58 | EXPORT_SYMBOL_GPL(get_proc_net); | 51 | EXPORT_SYMBOL_GPL(get_proc_net); |
59 | 52 | ||
60 | static struct proc_dir_entry *proc_net_shadow; | 53 | static struct proc_dir_entry *shadow_pde; |
61 | 54 | ||
62 | static struct dentry *proc_net_shadow_dentry(struct dentry *parent, | 55 | static struct proc_dir_entry *proc_net_shadow(struct task_struct *task, |
63 | struct proc_dir_entry *de) | 56 | struct proc_dir_entry *de) |
64 | { | 57 | { |
65 | struct dentry *shadow = NULL; | 58 | return task->nsproxy->net_ns->proc_net; |
66 | struct inode *inode; | ||
67 | if (!de) | ||
68 | goto out; | ||
69 | de_get(de); | ||
70 | inode = proc_get_inode(parent->d_inode->i_sb, de->low_ino, de); | ||
71 | if (!inode) | ||
72 | goto out_de_put; | ||
73 | shadow = d_alloc_name(parent, de->name); | ||
74 | if (!shadow) | ||
75 | goto out_iput; | ||
76 | shadow->d_op = parent->d_op; /* proc_dentry_operations */ | ||
77 | d_instantiate(shadow, inode); | ||
78 | out: | ||
79 | return shadow; | ||
80 | out_iput: | ||
81 | iput(inode); | ||
82 | out_de_put: | ||
83 | de_put(de); | ||
84 | goto out; | ||
85 | } | ||
86 | |||
87 | static void *proc_net_follow_link(struct dentry *parent, struct nameidata *nd) | ||
88 | { | ||
89 | struct net *net = current->nsproxy->net_ns; | ||
90 | struct dentry *shadow; | ||
91 | shadow = proc_net_shadow_dentry(parent, net->proc_net); | ||
92 | if (!shadow) | ||
93 | return ERR_PTR(-ENOENT); | ||
94 | |||
95 | dput(nd->dentry); | ||
96 | /* My dentry count is 1 and that should be enough as the | ||
97 | * shadow dentry is thrown away immediately. | ||
98 | */ | ||
99 | nd->dentry = shadow; | ||
100 | return NULL; | ||
101 | } | ||
102 | |||
103 | static struct dentry *proc_net_lookup(struct inode *dir, struct dentry *dentry, | ||
104 | struct nameidata *nd) | ||
105 | { | ||
106 | struct net *net = current->nsproxy->net_ns; | ||
107 | struct dentry *shadow; | ||
108 | |||
109 | shadow = proc_net_shadow_dentry(nd->dentry, net->proc_net); | ||
110 | if (!shadow) | ||
111 | return ERR_PTR(-ENOENT); | ||
112 | |||
113 | dput(nd->dentry); | ||
114 | nd->dentry = shadow; | ||
115 | |||
116 | return shadow->d_inode->i_op->lookup(shadow->d_inode, dentry, nd); | ||
117 | } | 59 | } |
118 | 60 | ||
119 | static int proc_net_setattr(struct dentry *dentry, struct iattr *iattr) | ||
120 | { | ||
121 | struct net *net = current->nsproxy->net_ns; | ||
122 | struct dentry *shadow; | ||
123 | int ret; | ||
124 | |||
125 | shadow = proc_net_shadow_dentry(dentry->d_parent, net->proc_net); | ||
126 | if (!shadow) | ||
127 | return -ENOENT; | ||
128 | ret = shadow->d_inode->i_op->setattr(shadow, iattr); | ||
129 | dput(shadow); | ||
130 | return ret; | ||
131 | } | ||
132 | |||
133 | static const struct file_operations proc_net_dir_operations = { | ||
134 | .read = generic_read_dir, | ||
135 | }; | ||
136 | |||
137 | static struct inode_operations proc_net_dir_inode_operations = { | ||
138 | .follow_link = proc_net_follow_link, | ||
139 | .lookup = proc_net_lookup, | ||
140 | .setattr = proc_net_setattr, | ||
141 | }; | ||
142 | |||
143 | static __net_init int proc_net_ns_init(struct net *net) | 61 | static __net_init int proc_net_ns_init(struct net *net) |
144 | { | 62 | { |
145 | struct proc_dir_entry *root, *netd, *net_statd; | 63 | struct proc_dir_entry *root, *netd, *net_statd; |
@@ -185,16 +103,15 @@ static __net_exit void proc_net_ns_exit(struct net *net) | |||
185 | kfree(net->proc_net_root); | 103 | kfree(net->proc_net_root); |
186 | } | 104 | } |
187 | 105 | ||
188 | struct pernet_operations __net_initdata proc_net_ns_ops = { | 106 | static struct pernet_operations __net_initdata proc_net_ns_ops = { |
189 | .init = proc_net_ns_init, | 107 | .init = proc_net_ns_init, |
190 | .exit = proc_net_ns_exit, | 108 | .exit = proc_net_ns_exit, |
191 | }; | 109 | }; |
192 | 110 | ||
193 | int __init proc_net_init(void) | 111 | int __init proc_net_init(void) |
194 | { | 112 | { |
195 | proc_net_shadow = proc_mkdir("net", NULL); | 113 | shadow_pde = proc_mkdir("net", NULL); |
196 | proc_net_shadow->proc_iops = &proc_net_dir_inode_operations; | 114 | shadow_pde->shadow_proc = proc_net_shadow; |
197 | proc_net_shadow->proc_fops = &proc_net_dir_operations; | ||
198 | 115 | ||
199 | return register_pernet_subsys(&proc_net_ns_ops); | 116 | return register_pernet_subsys(&proc_net_ns_ops); |
200 | } | 117 | } |
diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c index 680c429bfa22..4e57fcf85982 100644 --- a/fs/proc/proc_sysctl.c +++ b/fs/proc/proc_sysctl.c | |||
@@ -171,7 +171,8 @@ static ssize_t proc_sys_read(struct file *filp, char __user *buf, | |||
171 | struct dentry *dentry = filp->f_dentry; | 171 | struct dentry *dentry = filp->f_dentry; |
172 | struct ctl_table_header *head; | 172 | struct ctl_table_header *head; |
173 | struct ctl_table *table; | 173 | struct ctl_table *table; |
174 | ssize_t error, res; | 174 | ssize_t error; |
175 | size_t res; | ||
175 | 176 | ||
176 | table = do_proc_sys_lookup(dentry->d_parent, &dentry->d_name, &head); | 177 | table = do_proc_sys_lookup(dentry->d_parent, &dentry->d_name, &head); |
177 | /* Has the sysctl entry disappeared on us? */ | 178 | /* Has the sysctl entry disappeared on us? */ |
@@ -209,7 +210,8 @@ static ssize_t proc_sys_write(struct file *filp, const char __user *buf, | |||
209 | struct dentry *dentry = filp->f_dentry; | 210 | struct dentry *dentry = filp->f_dentry; |
210 | struct ctl_table_header *head; | 211 | struct ctl_table_header *head; |
211 | struct ctl_table *table; | 212 | struct ctl_table *table; |
212 | ssize_t error, res; | 213 | ssize_t error; |
214 | size_t res; | ||
213 | 215 | ||
214 | table = do_proc_sys_lookup(dentry->d_parent, &dentry->d_name, &head); | 216 | table = do_proc_sys_lookup(dentry->d_parent, &dentry->d_name, &head); |
215 | /* Has the sysctl entry disappeared on us? */ | 217 | /* Has the sysctl entry disappeared on us? */ |
diff --git a/fs/proc/root.c b/fs/proc/root.c index cf3046638b09..81f99e691f99 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c | |||
@@ -18,32 +18,90 @@ | |||
18 | #include <linux/bitops.h> | 18 | #include <linux/bitops.h> |
19 | #include <linux/smp_lock.h> | 19 | #include <linux/smp_lock.h> |
20 | #include <linux/mount.h> | 20 | #include <linux/mount.h> |
21 | #include <linux/pid_namespace.h> | ||
21 | 22 | ||
22 | #include "internal.h" | 23 | #include "internal.h" |
23 | 24 | ||
24 | struct proc_dir_entry *proc_bus, *proc_root_fs, *proc_root_driver; | 25 | struct proc_dir_entry *proc_bus, *proc_root_fs, *proc_root_driver; |
25 | 26 | ||
27 | static int proc_test_super(struct super_block *sb, void *data) | ||
28 | { | ||
29 | return sb->s_fs_info == data; | ||
30 | } | ||
31 | |||
32 | static int proc_set_super(struct super_block *sb, void *data) | ||
33 | { | ||
34 | struct pid_namespace *ns; | ||
35 | |||
36 | ns = (struct pid_namespace *)data; | ||
37 | sb->s_fs_info = get_pid_ns(ns); | ||
38 | return set_anon_super(sb, NULL); | ||
39 | } | ||
40 | |||
26 | static int proc_get_sb(struct file_system_type *fs_type, | 41 | static int proc_get_sb(struct file_system_type *fs_type, |
27 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) | 42 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) |
28 | { | 43 | { |
44 | int err; | ||
45 | struct super_block *sb; | ||
46 | struct pid_namespace *ns; | ||
47 | struct proc_inode *ei; | ||
48 | |||
29 | if (proc_mnt) { | 49 | if (proc_mnt) { |
30 | /* Seed the root directory with a pid so it doesn't need | 50 | /* Seed the root directory with a pid so it doesn't need |
31 | * to be special in base.c. I would do this earlier but | 51 | * to be special in base.c. I would do this earlier but |
32 | * the only task alive when /proc is mounted the first time | 52 | * the only task alive when /proc is mounted the first time |
33 | * is the init_task and it doesn't have any pids. | 53 | * is the init_task and it doesn't have any pids. |
34 | */ | 54 | */ |
35 | struct proc_inode *ei; | ||
36 | ei = PROC_I(proc_mnt->mnt_sb->s_root->d_inode); | 55 | ei = PROC_I(proc_mnt->mnt_sb->s_root->d_inode); |
37 | if (!ei->pid) | 56 | if (!ei->pid) |
38 | ei->pid = find_get_pid(1); | 57 | ei->pid = find_get_pid(1); |
39 | } | 58 | } |
40 | return get_sb_single(fs_type, flags, data, proc_fill_super, mnt); | 59 | |
60 | if (flags & MS_KERNMOUNT) | ||
61 | ns = (struct pid_namespace *)data; | ||
62 | else | ||
63 | ns = current->nsproxy->pid_ns; | ||
64 | |||
65 | sb = sget(fs_type, proc_test_super, proc_set_super, ns); | ||
66 | if (IS_ERR(sb)) | ||
67 | return PTR_ERR(sb); | ||
68 | |||
69 | if (!sb->s_root) { | ||
70 | sb->s_flags = flags; | ||
71 | err = proc_fill_super(sb); | ||
72 | if (err) { | ||
73 | up_write(&sb->s_umount); | ||
74 | deactivate_super(sb); | ||
75 | return err; | ||
76 | } | ||
77 | |||
78 | ei = PROC_I(sb->s_root->d_inode); | ||
79 | if (!ei->pid) { | ||
80 | rcu_read_lock(); | ||
81 | ei->pid = get_pid(find_pid_ns(1, ns)); | ||
82 | rcu_read_unlock(); | ||
83 | } | ||
84 | |||
85 | sb->s_flags |= MS_ACTIVE; | ||
86 | ns->proc_mnt = mnt; | ||
87 | } | ||
88 | |||
89 | return simple_set_mnt(mnt, sb); | ||
90 | } | ||
91 | |||
92 | static void proc_kill_sb(struct super_block *sb) | ||
93 | { | ||
94 | struct pid_namespace *ns; | ||
95 | |||
96 | ns = (struct pid_namespace *)sb->s_fs_info; | ||
97 | kill_anon_super(sb); | ||
98 | put_pid_ns(ns); | ||
41 | } | 99 | } |
42 | 100 | ||
43 | static struct file_system_type proc_fs_type = { | 101 | static struct file_system_type proc_fs_type = { |
44 | .name = "proc", | 102 | .name = "proc", |
45 | .get_sb = proc_get_sb, | 103 | .get_sb = proc_get_sb, |
46 | .kill_sb = kill_anon_super, | 104 | .kill_sb = proc_kill_sb, |
47 | }; | 105 | }; |
48 | 106 | ||
49 | void __init proc_root_init(void) | 107 | void __init proc_root_init(void) |
@@ -54,12 +112,13 @@ void __init proc_root_init(void) | |||
54 | err = register_filesystem(&proc_fs_type); | 112 | err = register_filesystem(&proc_fs_type); |
55 | if (err) | 113 | if (err) |
56 | return; | 114 | return; |
57 | proc_mnt = kern_mount(&proc_fs_type); | 115 | proc_mnt = kern_mount_data(&proc_fs_type, &init_pid_ns); |
58 | err = PTR_ERR(proc_mnt); | 116 | err = PTR_ERR(proc_mnt); |
59 | if (IS_ERR(proc_mnt)) { | 117 | if (IS_ERR(proc_mnt)) { |
60 | unregister_filesystem(&proc_fs_type); | 118 | unregister_filesystem(&proc_fs_type); |
61 | return; | 119 | return; |
62 | } | 120 | } |
121 | |||
63 | proc_misc_init(); | 122 | proc_misc_init(); |
64 | 123 | ||
65 | proc_net_init(); | 124 | proc_net_init(); |
@@ -148,11 +207,28 @@ struct proc_dir_entry proc_root = { | |||
148 | .name = "/proc", | 207 | .name = "/proc", |
149 | .mode = S_IFDIR | S_IRUGO | S_IXUGO, | 208 | .mode = S_IFDIR | S_IRUGO | S_IXUGO, |
150 | .nlink = 2, | 209 | .nlink = 2, |
210 | .count = ATOMIC_INIT(1), | ||
151 | .proc_iops = &proc_root_inode_operations, | 211 | .proc_iops = &proc_root_inode_operations, |
152 | .proc_fops = &proc_root_operations, | 212 | .proc_fops = &proc_root_operations, |
153 | .parent = &proc_root, | 213 | .parent = &proc_root, |
154 | }; | 214 | }; |
155 | 215 | ||
216 | int pid_ns_prepare_proc(struct pid_namespace *ns) | ||
217 | { | ||
218 | struct vfsmount *mnt; | ||
219 | |||
220 | mnt = kern_mount_data(&proc_fs_type, ns); | ||
221 | if (IS_ERR(mnt)) | ||
222 | return PTR_ERR(mnt); | ||
223 | |||
224 | return 0; | ||
225 | } | ||
226 | |||
227 | void pid_ns_release_proc(struct pid_namespace *ns) | ||
228 | { | ||
229 | mntput(ns->proc_mnt); | ||
230 | } | ||
231 | |||
156 | EXPORT_SYMBOL(proc_symlink); | 232 | EXPORT_SYMBOL(proc_symlink); |
157 | EXPORT_SYMBOL(proc_mkdir); | 233 | EXPORT_SYMBOL(proc_mkdir); |
158 | EXPORT_SYMBOL(create_proc_entry); | 234 | EXPORT_SYMBOL(create_proc_entry); |
diff --git a/fs/read_write.c b/fs/read_write.c index 124693e8d3fa..ea1f94cc722e 100644 --- a/fs/read_write.c +++ b/fs/read_write.c | |||
@@ -370,7 +370,7 @@ asmlinkage ssize_t sys_read(unsigned int fd, char __user * buf, size_t count) | |||
370 | 370 | ||
371 | return ret; | 371 | return ret; |
372 | } | 372 | } |
373 | EXPORT_SYMBOL_GPL(sys_read); | 373 | EXPORT_UNUSED_SYMBOL_GPL(sys_read); /* to be deleted for 2.6.25 */ |
374 | 374 | ||
375 | asmlinkage ssize_t sys_write(unsigned int fd, const char __user * buf, size_t count) | 375 | asmlinkage ssize_t sys_write(unsigned int fd, const char __user * buf, size_t count) |
376 | { | 376 | { |
diff --git a/fs/reiserfs/bitmap.c b/fs/reiserfs/bitmap.c index 2a5dd34649b3..16b331dd9913 100644 --- a/fs/reiserfs/bitmap.c +++ b/fs/reiserfs/bitmap.c | |||
@@ -47,7 +47,9 @@ | |||
47 | test_bit(_ALLOC_ ## optname , &SB_ALLOC_OPTS(s)) | 47 | test_bit(_ALLOC_ ## optname , &SB_ALLOC_OPTS(s)) |
48 | 48 | ||
49 | static inline void get_bit_address(struct super_block *s, | 49 | static inline void get_bit_address(struct super_block *s, |
50 | b_blocknr_t block, int *bmap_nr, int *offset) | 50 | b_blocknr_t block, |
51 | unsigned int *bmap_nr, | ||
52 | unsigned int *offset) | ||
51 | { | 53 | { |
52 | /* It is in the bitmap block number equal to the block | 54 | /* It is in the bitmap block number equal to the block |
53 | * number divided by the number of bits in a block. */ | 55 | * number divided by the number of bits in a block. */ |
@@ -56,10 +58,10 @@ static inline void get_bit_address(struct super_block *s, | |||
56 | *offset = block & ((s->s_blocksize << 3) - 1); | 58 | *offset = block & ((s->s_blocksize << 3) - 1); |
57 | } | 59 | } |
58 | 60 | ||
59 | #ifdef CONFIG_REISERFS_CHECK | ||
60 | int is_reusable(struct super_block *s, b_blocknr_t block, int bit_value) | 61 | int is_reusable(struct super_block *s, b_blocknr_t block, int bit_value) |
61 | { | 62 | { |
62 | int bmap, offset; | 63 | unsigned int bmap, offset; |
64 | unsigned int bmap_count = reiserfs_bmap_count(s); | ||
63 | 65 | ||
64 | if (block == 0 || block >= SB_BLOCK_COUNT(s)) { | 66 | if (block == 0 || block >= SB_BLOCK_COUNT(s)) { |
65 | reiserfs_warning(s, | 67 | reiserfs_warning(s, |
@@ -75,25 +77,26 @@ int is_reusable(struct super_block *s, b_blocknr_t block, int bit_value) | |||
75 | if (unlikely(test_bit(REISERFS_OLD_FORMAT, | 77 | if (unlikely(test_bit(REISERFS_OLD_FORMAT, |
76 | &(REISERFS_SB(s)->s_properties)))) { | 78 | &(REISERFS_SB(s)->s_properties)))) { |
77 | b_blocknr_t bmap1 = REISERFS_SB(s)->s_sbh->b_blocknr + 1; | 79 | b_blocknr_t bmap1 = REISERFS_SB(s)->s_sbh->b_blocknr + 1; |
78 | if (block >= bmap1 && block <= bmap1 + SB_BMAP_NR(s)) { | 80 | if (block >= bmap1 && |
81 | block <= bmap1 + bmap_count) { | ||
79 | reiserfs_warning(s, "vs: 4019: is_reusable: " | 82 | reiserfs_warning(s, "vs: 4019: is_reusable: " |
80 | "bitmap block %lu(%u) can't be freed or reused", | 83 | "bitmap block %lu(%u) can't be freed or reused", |
81 | block, SB_BMAP_NR(s)); | 84 | block, bmap_count); |
82 | return 0; | 85 | return 0; |
83 | } | 86 | } |
84 | } else { | 87 | } else { |
85 | if (offset == 0) { | 88 | if (offset == 0) { |
86 | reiserfs_warning(s, "vs: 4020: is_reusable: " | 89 | reiserfs_warning(s, "vs: 4020: is_reusable: " |
87 | "bitmap block %lu(%u) can't be freed or reused", | 90 | "bitmap block %lu(%u) can't be freed or reused", |
88 | block, SB_BMAP_NR(s)); | 91 | block, bmap_count); |
89 | return 0; | 92 | return 0; |
90 | } | 93 | } |
91 | } | 94 | } |
92 | 95 | ||
93 | if (bmap >= SB_BMAP_NR(s)) { | 96 | if (bmap >= bmap_count) { |
94 | reiserfs_warning(s, | 97 | reiserfs_warning(s, |
95 | "vs-4030: is_reusable: there is no so many bitmap blocks: " | 98 | "vs-4030: is_reusable: there is no so many bitmap blocks: " |
96 | "block=%lu, bitmap_nr=%d", block, bmap); | 99 | "block=%lu, bitmap_nr=%u", block, bmap); |
97 | return 0; | 100 | return 0; |
98 | } | 101 | } |
99 | 102 | ||
@@ -106,12 +109,11 @@ int is_reusable(struct super_block *s, b_blocknr_t block, int bit_value) | |||
106 | 109 | ||
107 | return 1; | 110 | return 1; |
108 | } | 111 | } |
109 | #endif /* CONFIG_REISERFS_CHECK */ | ||
110 | 112 | ||
111 | /* searches in journal structures for a given block number (bmap, off). If block | 113 | /* searches in journal structures for a given block number (bmap, off). If block |
112 | is found in reiserfs journal it suggests next free block candidate to test. */ | 114 | is found in reiserfs journal it suggests next free block candidate to test. */ |
113 | static inline int is_block_in_journal(struct super_block *s, int bmap, int | 115 | static inline int is_block_in_journal(struct super_block *s, unsigned int bmap, |
114 | off, int *next) | 116 | int off, int *next) |
115 | { | 117 | { |
116 | b_blocknr_t tmp; | 118 | b_blocknr_t tmp; |
117 | 119 | ||
@@ -132,8 +134,8 @@ static inline int is_block_in_journal(struct super_block *s, int bmap, int | |||
132 | /* it searches for a window of zero bits with given minimum and maximum lengths in one bitmap | 134 | /* it searches for a window of zero bits with given minimum and maximum lengths in one bitmap |
133 | * block; */ | 135 | * block; */ |
134 | static int scan_bitmap_block(struct reiserfs_transaction_handle *th, | 136 | static int scan_bitmap_block(struct reiserfs_transaction_handle *th, |
135 | int bmap_n, int *beg, int boundary, int min, | 137 | unsigned int bmap_n, int *beg, int boundary, |
136 | int max, int unfm) | 138 | int min, int max, int unfm) |
137 | { | 139 | { |
138 | struct super_block *s = th->t_super; | 140 | struct super_block *s = th->t_super; |
139 | struct reiserfs_bitmap_info *bi = &SB_AP_BITMAP(s)[bmap_n]; | 141 | struct reiserfs_bitmap_info *bi = &SB_AP_BITMAP(s)[bmap_n]; |
@@ -143,8 +145,8 @@ static int scan_bitmap_block(struct reiserfs_transaction_handle *th, | |||
143 | 145 | ||
144 | BUG_ON(!th->t_trans_id); | 146 | BUG_ON(!th->t_trans_id); |
145 | 147 | ||
146 | RFALSE(bmap_n >= SB_BMAP_NR(s), "Bitmap %d is out of range (0..%d)", | 148 | RFALSE(bmap_n >= reiserfs_bmap_count(s), "Bitmap %u is out of " |
147 | bmap_n, SB_BMAP_NR(s) - 1); | 149 | "range (0..%u)", bmap_n, reiserfs_bmap_count(s) - 1); |
148 | PROC_INFO_INC(s, scan_bitmap.bmap); | 150 | PROC_INFO_INC(s, scan_bitmap.bmap); |
149 | /* this is unclear and lacks comments, explain how journal bitmaps | 151 | /* this is unclear and lacks comments, explain how journal bitmaps |
150 | work here for the reader. Convey a sense of the design here. What | 152 | work here for the reader. Convey a sense of the design here. What |
@@ -249,12 +251,12 @@ static int bmap_hash_id(struct super_block *s, u32 id) | |||
249 | } else { | 251 | } else { |
250 | hash_in = (char *)(&id); | 252 | hash_in = (char *)(&id); |
251 | hash = keyed_hash(hash_in, 4); | 253 | hash = keyed_hash(hash_in, 4); |
252 | bm = hash % SB_BMAP_NR(s); | 254 | bm = hash % reiserfs_bmap_count(s); |
253 | if (!bm) | 255 | if (!bm) |
254 | bm = 1; | 256 | bm = 1; |
255 | } | 257 | } |
256 | /* this can only be true when SB_BMAP_NR = 1 */ | 258 | /* this can only be true when SB_BMAP_NR = 1 */ |
257 | if (bm >= SB_BMAP_NR(s)) | 259 | if (bm >= reiserfs_bmap_count(s)) |
258 | bm = 0; | 260 | bm = 0; |
259 | return bm; | 261 | return bm; |
260 | } | 262 | } |
@@ -273,7 +275,7 @@ static inline int block_group_used(struct super_block *s, u32 id) | |||
273 | * to make a better decision. This favors long-term performace gain | 275 | * to make a better decision. This favors long-term performace gain |
274 | * with a better on-disk layout vs. a short term gain of skipping the | 276 | * with a better on-disk layout vs. a short term gain of skipping the |
275 | * read and potentially having a bad placement. */ | 277 | * read and potentially having a bad placement. */ |
276 | if (info->first_zero_hint == 0) { | 278 | if (info->free_count == UINT_MAX) { |
277 | struct buffer_head *bh = reiserfs_read_bitmap_block(s, bm); | 279 | struct buffer_head *bh = reiserfs_read_bitmap_block(s, bm); |
278 | brelse(bh); | 280 | brelse(bh); |
279 | } | 281 | } |
@@ -309,16 +311,16 @@ __le32 reiserfs_choose_packing(struct inode * dir) | |||
309 | * bitmap and place new blocks there. Returns number of allocated blocks. */ | 311 | * bitmap and place new blocks there. Returns number of allocated blocks. */ |
310 | static int scan_bitmap(struct reiserfs_transaction_handle *th, | 312 | static int scan_bitmap(struct reiserfs_transaction_handle *th, |
311 | b_blocknr_t * start, b_blocknr_t finish, | 313 | b_blocknr_t * start, b_blocknr_t finish, |
312 | int min, int max, int unfm, unsigned long file_block) | 314 | int min, int max, int unfm, sector_t file_block) |
313 | { | 315 | { |
314 | int nr_allocated = 0; | 316 | int nr_allocated = 0; |
315 | struct super_block *s = th->t_super; | 317 | struct super_block *s = th->t_super; |
316 | /* find every bm and bmap and bmap_nr in this file, and change them all to bitmap_blocknr | 318 | /* find every bm and bmap and bmap_nr in this file, and change them all to bitmap_blocknr |
317 | * - Hans, it is not a block number - Zam. */ | 319 | * - Hans, it is not a block number - Zam. */ |
318 | 320 | ||
319 | int bm, off; | 321 | unsigned int bm, off; |
320 | int end_bm, end_off; | 322 | unsigned int end_bm, end_off; |
321 | int off_max = s->s_blocksize << 3; | 323 | unsigned int off_max = s->s_blocksize << 3; |
322 | 324 | ||
323 | BUG_ON(!th->t_trans_id); | 325 | BUG_ON(!th->t_trans_id); |
324 | 326 | ||
@@ -328,10 +330,10 @@ static int scan_bitmap(struct reiserfs_transaction_handle *th, | |||
328 | 330 | ||
329 | get_bit_address(s, *start, &bm, &off); | 331 | get_bit_address(s, *start, &bm, &off); |
330 | get_bit_address(s, finish, &end_bm, &end_off); | 332 | get_bit_address(s, finish, &end_bm, &end_off); |
331 | if (bm > SB_BMAP_NR(s)) | 333 | if (bm > reiserfs_bmap_count(s)) |
332 | return 0; | 334 | return 0; |
333 | if (end_bm > SB_BMAP_NR(s)) | 335 | if (end_bm > reiserfs_bmap_count(s)) |
334 | end_bm = SB_BMAP_NR(s); | 336 | end_bm = reiserfs_bmap_count(s); |
335 | 337 | ||
336 | /* When the bitmap is more than 10% free, anyone can allocate. | 338 | /* When the bitmap is more than 10% free, anyone can allocate. |
337 | * When it's less than 10% free, only files that already use the | 339 | * When it's less than 10% free, only files that already use the |
@@ -385,7 +387,7 @@ static void _reiserfs_free_block(struct reiserfs_transaction_handle *th, | |||
385 | struct reiserfs_super_block *rs; | 387 | struct reiserfs_super_block *rs; |
386 | struct buffer_head *sbh, *bmbh; | 388 | struct buffer_head *sbh, *bmbh; |
387 | struct reiserfs_bitmap_info *apbi; | 389 | struct reiserfs_bitmap_info *apbi; |
388 | int nr, offset; | 390 | unsigned int nr, offset; |
389 | 391 | ||
390 | BUG_ON(!th->t_trans_id); | 392 | BUG_ON(!th->t_trans_id); |
391 | 393 | ||
@@ -397,10 +399,12 @@ static void _reiserfs_free_block(struct reiserfs_transaction_handle *th, | |||
397 | 399 | ||
398 | get_bit_address(s, block, &nr, &offset); | 400 | get_bit_address(s, block, &nr, &offset); |
399 | 401 | ||
400 | if (nr >= sb_bmap_nr(rs)) { | 402 | if (nr >= reiserfs_bmap_count(s)) { |
401 | reiserfs_warning(s, "vs-4075: reiserfs_free_block: " | 403 | reiserfs_warning(s, "vs-4075: reiserfs_free_block: " |
402 | "block %lu is out of range on %s", | 404 | "block %lu is out of range on %s " |
403 | block, reiserfs_bdevname(s)); | 405 | "(nr=%u,max=%u)", block, |
406 | reiserfs_bdevname(s), nr, | ||
407 | reiserfs_bmap_count(s)); | ||
404 | return; | 408 | return; |
405 | } | 409 | } |
406 | 410 | ||
@@ -434,12 +438,19 @@ void reiserfs_free_block(struct reiserfs_transaction_handle *th, | |||
434 | int for_unformatted) | 438 | int for_unformatted) |
435 | { | 439 | { |
436 | struct super_block *s = th->t_super; | 440 | struct super_block *s = th->t_super; |
437 | |||
438 | BUG_ON(!th->t_trans_id); | 441 | BUG_ON(!th->t_trans_id); |
439 | 442 | ||
440 | RFALSE(!s, "vs-4061: trying to free block on nonexistent device"); | 443 | RFALSE(!s, "vs-4061: trying to free block on nonexistent device"); |
441 | RFALSE(is_reusable(s, block, 1) == 0, | 444 | if (!is_reusable(s, block, 1)) |
442 | "vs-4071: can not free such block"); | 445 | return; |
446 | |||
447 | if (block > sb_block_count(REISERFS_SB(s)->s_rs)) { | ||
448 | reiserfs_panic(th->t_super, "bitmap-4072", | ||
449 | "Trying to free block outside file system " | ||
450 | "boundaries (%lu > %lu)", | ||
451 | block, sb_block_count(REISERFS_SB(s)->s_rs)); | ||
452 | return; | ||
453 | } | ||
443 | /* mark it before we clear it, just in case */ | 454 | /* mark it before we clear it, just in case */ |
444 | journal_mark_freed(th, s, block); | 455 | journal_mark_freed(th, s, block); |
445 | _reiserfs_free_block(th, inode, block, for_unformatted); | 456 | _reiserfs_free_block(th, inode, block, for_unformatted); |
@@ -449,11 +460,11 @@ void reiserfs_free_block(struct reiserfs_transaction_handle *th, | |||
449 | static void reiserfs_free_prealloc_block(struct reiserfs_transaction_handle *th, | 460 | static void reiserfs_free_prealloc_block(struct reiserfs_transaction_handle *th, |
450 | struct inode *inode, b_blocknr_t block) | 461 | struct inode *inode, b_blocknr_t block) |
451 | { | 462 | { |
463 | BUG_ON(!th->t_trans_id); | ||
452 | RFALSE(!th->t_super, | 464 | RFALSE(!th->t_super, |
453 | "vs-4060: trying to free block on nonexistent device"); | 465 | "vs-4060: trying to free block on nonexistent device"); |
454 | RFALSE(is_reusable(th->t_super, block, 1) == 0, | 466 | if (!is_reusable(th->t_super, block, 1)) |
455 | "vs-4070: can not free such block"); | 467 | return; |
456 | BUG_ON(!th->t_trans_id); | ||
457 | _reiserfs_free_block(th, inode, block, 1); | 468 | _reiserfs_free_block(th, inode, block, 1); |
458 | } | 469 | } |
459 | 470 | ||
@@ -1207,27 +1218,22 @@ void reiserfs_cache_bitmap_metadata(struct super_block *sb, | |||
1207 | { | 1218 | { |
1208 | unsigned long *cur = (unsigned long *)(bh->b_data + bh->b_size); | 1219 | unsigned long *cur = (unsigned long *)(bh->b_data + bh->b_size); |
1209 | 1220 | ||
1210 | info->first_zero_hint = 1 << (sb->s_blocksize_bits + 3); | 1221 | /* The first bit must ALWAYS be 1 */ |
1222 | BUG_ON(!reiserfs_test_le_bit(0, (unsigned long *)bh->b_data)); | ||
1223 | |||
1224 | info->free_count = 0; | ||
1211 | 1225 | ||
1212 | while (--cur >= (unsigned long *)bh->b_data) { | 1226 | while (--cur >= (unsigned long *)bh->b_data) { |
1213 | int base = ((char *)cur - bh->b_data) << 3; | 1227 | int i; |
1214 | 1228 | ||
1215 | /* 0 and ~0 are special, we can optimize for them */ | 1229 | /* 0 and ~0 are special, we can optimize for them */ |
1216 | if (*cur == 0) { | 1230 | if (*cur == 0) |
1217 | info->first_zero_hint = base; | ||
1218 | info->free_count += BITS_PER_LONG; | 1231 | info->free_count += BITS_PER_LONG; |
1219 | } else if (*cur != ~0L) { /* A mix, investigate */ | 1232 | else if (*cur != ~0L) /* A mix, investigate */ |
1220 | int b; | 1233 | for (i = BITS_PER_LONG - 1; i >= 0; i--) |
1221 | for (b = BITS_PER_LONG - 1; b >= 0; b--) { | 1234 | if (!reiserfs_test_le_bit(i, cur)) |
1222 | if (!reiserfs_test_le_bit(b, cur)) { | ||
1223 | info->first_zero_hint = base + b; | ||
1224 | info->free_count++; | 1235 | info->free_count++; |
1225 | } | ||
1226 | } | ||
1227 | } | ||
1228 | } | 1236 | } |
1229 | /* The first bit must ALWAYS be 1 */ | ||
1230 | BUG_ON(info->first_zero_hint == 0); | ||
1231 | } | 1237 | } |
1232 | 1238 | ||
1233 | struct buffer_head *reiserfs_read_bitmap_block(struct super_block *sb, | 1239 | struct buffer_head *reiserfs_read_bitmap_block(struct super_block *sb, |
@@ -1257,7 +1263,7 @@ struct buffer_head *reiserfs_read_bitmap_block(struct super_block *sb, | |||
1257 | BUG_ON(!buffer_uptodate(bh)); | 1263 | BUG_ON(!buffer_uptodate(bh)); |
1258 | BUG_ON(atomic_read(&bh->b_count) == 0); | 1264 | BUG_ON(atomic_read(&bh->b_count) == 0); |
1259 | 1265 | ||
1260 | if (info->first_zero_hint == 0) | 1266 | if (info->free_count == UINT_MAX) |
1261 | reiserfs_cache_bitmap_metadata(sb, bh, info); | 1267 | reiserfs_cache_bitmap_metadata(sb, bh, info); |
1262 | } | 1268 | } |
1263 | 1269 | ||
@@ -1267,12 +1273,13 @@ struct buffer_head *reiserfs_read_bitmap_block(struct super_block *sb, | |||
1267 | int reiserfs_init_bitmap_cache(struct super_block *sb) | 1273 | int reiserfs_init_bitmap_cache(struct super_block *sb) |
1268 | { | 1274 | { |
1269 | struct reiserfs_bitmap_info *bitmap; | 1275 | struct reiserfs_bitmap_info *bitmap; |
1276 | unsigned int bmap_nr = reiserfs_bmap_count(sb); | ||
1270 | 1277 | ||
1271 | bitmap = vmalloc(sizeof (*bitmap) * SB_BMAP_NR(sb)); | 1278 | bitmap = vmalloc(sizeof(*bitmap) * bmap_nr); |
1272 | if (bitmap == NULL) | 1279 | if (bitmap == NULL) |
1273 | return -ENOMEM; | 1280 | return -ENOMEM; |
1274 | 1281 | ||
1275 | memset(bitmap, 0, sizeof (*bitmap) * SB_BMAP_NR(sb)); | 1282 | memset(bitmap, 0xff, sizeof(*bitmap) * bmap_nr); |
1276 | 1283 | ||
1277 | SB_AP_BITMAP(sb) = bitmap; | 1284 | SB_AP_BITMAP(sb) = bitmap; |
1278 | 1285 | ||
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c index 0804289d355d..231fd5ccadc5 100644 --- a/fs/reiserfs/inode.c +++ b/fs/reiserfs/inode.c | |||
@@ -199,7 +199,7 @@ static inline void set_block_dev_mapped(struct buffer_head *bh, | |||
199 | // files which were created in the earlier version can not be longer, | 199 | // files which were created in the earlier version can not be longer, |
200 | // than 2 gb | 200 | // than 2 gb |
201 | // | 201 | // |
202 | static int file_capable(struct inode *inode, long block) | 202 | static int file_capable(struct inode *inode, sector_t block) |
203 | { | 203 | { |
204 | if (get_inode_item_key_version(inode) != KEY_FORMAT_3_5 || // it is new file. | 204 | if (get_inode_item_key_version(inode) != KEY_FORMAT_3_5 || // it is new file. |
205 | block < (1 << (31 - inode->i_sb->s_blocksize_bits))) // old file, but 'block' is inside of 2gb | 205 | block < (1 << (31 - inode->i_sb->s_blocksize_bits))) // old file, but 'block' is inside of 2gb |
@@ -242,7 +242,7 @@ static int restart_transaction(struct reiserfs_transaction_handle *th, | |||
242 | // Please improve the english/clarity in the comment above, as it is | 242 | // Please improve the english/clarity in the comment above, as it is |
243 | // hard to understand. | 243 | // hard to understand. |
244 | 244 | ||
245 | static int _get_block_create_0(struct inode *inode, long block, | 245 | static int _get_block_create_0(struct inode *inode, sector_t block, |
246 | struct buffer_head *bh_result, int args) | 246 | struct buffer_head *bh_result, int args) |
247 | { | 247 | { |
248 | INITIALIZE_PATH(path); | 248 | INITIALIZE_PATH(path); |
@@ -250,7 +250,7 @@ static int _get_block_create_0(struct inode *inode, long block, | |||
250 | struct buffer_head *bh; | 250 | struct buffer_head *bh; |
251 | struct item_head *ih, tmp_ih; | 251 | struct item_head *ih, tmp_ih; |
252 | int fs_gen; | 252 | int fs_gen; |
253 | int blocknr; | 253 | b_blocknr_t blocknr; |
254 | char *p = NULL; | 254 | char *p = NULL; |
255 | int chars; | 255 | int chars; |
256 | int ret; | 256 | int ret; |
@@ -569,7 +569,7 @@ static int convert_tail_for_hole(struct inode *inode, | |||
569 | } | 569 | } |
570 | 570 | ||
571 | static inline int _allocate_block(struct reiserfs_transaction_handle *th, | 571 | static inline int _allocate_block(struct reiserfs_transaction_handle *th, |
572 | long block, | 572 | sector_t block, |
573 | struct inode *inode, | 573 | struct inode *inode, |
574 | b_blocknr_t * allocated_block_nr, | 574 | b_blocknr_t * allocated_block_nr, |
575 | struct treepath *path, int flags) | 575 | struct treepath *path, int flags) |
@@ -1515,19 +1515,20 @@ struct inode *reiserfs_iget(struct super_block *s, const struct cpu_key *key) | |||
1515 | return inode; | 1515 | return inode; |
1516 | } | 1516 | } |
1517 | 1517 | ||
1518 | struct dentry *reiserfs_get_dentry(struct super_block *sb, void *vobjp) | 1518 | static struct dentry *reiserfs_get_dentry(struct super_block *sb, |
1519 | u32 objectid, u32 dir_id, u32 generation) | ||
1520 | |||
1519 | { | 1521 | { |
1520 | __u32 *data = vobjp; | ||
1521 | struct cpu_key key; | 1522 | struct cpu_key key; |
1522 | struct dentry *result; | 1523 | struct dentry *result; |
1523 | struct inode *inode; | 1524 | struct inode *inode; |
1524 | 1525 | ||
1525 | key.on_disk_key.k_objectid = data[0]; | 1526 | key.on_disk_key.k_objectid = objectid; |
1526 | key.on_disk_key.k_dir_id = data[1]; | 1527 | key.on_disk_key.k_dir_id = dir_id; |
1527 | reiserfs_write_lock(sb); | 1528 | reiserfs_write_lock(sb); |
1528 | inode = reiserfs_iget(sb, &key); | 1529 | inode = reiserfs_iget(sb, &key); |
1529 | if (inode && !IS_ERR(inode) && data[2] != 0 && | 1530 | if (inode && !IS_ERR(inode) && generation != 0 && |
1530 | data[2] != inode->i_generation) { | 1531 | generation != inode->i_generation) { |
1531 | iput(inode); | 1532 | iput(inode); |
1532 | inode = NULL; | 1533 | inode = NULL; |
1533 | } | 1534 | } |
@@ -1544,14 +1545,9 @@ struct dentry *reiserfs_get_dentry(struct super_block *sb, void *vobjp) | |||
1544 | return result; | 1545 | return result; |
1545 | } | 1546 | } |
1546 | 1547 | ||
1547 | struct dentry *reiserfs_decode_fh(struct super_block *sb, __u32 * data, | 1548 | struct dentry *reiserfs_fh_to_dentry(struct super_block *sb, struct fid *fid, |
1548 | int len, int fhtype, | 1549 | int fh_len, int fh_type) |
1549 | int (*acceptable) (void *contect, | ||
1550 | struct dentry * de), | ||
1551 | void *context) | ||
1552 | { | 1550 | { |
1553 | __u32 obj[3], parent[3]; | ||
1554 | |||
1555 | /* fhtype happens to reflect the number of u32s encoded. | 1551 | /* fhtype happens to reflect the number of u32s encoded. |
1556 | * due to a bug in earlier code, fhtype might indicate there | 1552 | * due to a bug in earlier code, fhtype might indicate there |
1557 | * are more u32s then actually fitted. | 1553 | * are more u32s then actually fitted. |
@@ -1564,32 +1560,28 @@ struct dentry *reiserfs_decode_fh(struct super_block *sb, __u32 * data, | |||
1564 | * 6 - as above plus generation of directory | 1560 | * 6 - as above plus generation of directory |
1565 | * 6 does not fit in NFSv2 handles | 1561 | * 6 does not fit in NFSv2 handles |
1566 | */ | 1562 | */ |
1567 | if (fhtype > len) { | 1563 | if (fh_type > fh_len) { |
1568 | if (fhtype != 6 || len != 5) | 1564 | if (fh_type != 6 || fh_len != 5) |
1569 | reiserfs_warning(sb, | 1565 | reiserfs_warning(sb, |
1570 | "nfsd/reiserfs, fhtype=%d, len=%d - odd", | 1566 | "nfsd/reiserfs, fhtype=%d, len=%d - odd", |
1571 | fhtype, len); | 1567 | fh_type, fh_len); |
1572 | fhtype = 5; | 1568 | fh_type = 5; |
1573 | } | 1569 | } |
1574 | 1570 | ||
1575 | obj[0] = data[0]; | 1571 | return reiserfs_get_dentry(sb, fid->raw[0], fid->raw[1], |
1576 | obj[1] = data[1]; | 1572 | (fh_type == 3 || fh_type >= 5) ? fid->raw[2] : 0); |
1577 | if (fhtype == 3 || fhtype >= 5) | 1573 | } |
1578 | obj[2] = data[2]; | ||
1579 | else | ||
1580 | obj[2] = 0; /* generation number */ | ||
1581 | 1574 | ||
1582 | if (fhtype >= 4) { | 1575 | struct dentry *reiserfs_fh_to_parent(struct super_block *sb, struct fid *fid, |
1583 | parent[0] = data[fhtype >= 5 ? 3 : 2]; | 1576 | int fh_len, int fh_type) |
1584 | parent[1] = data[fhtype >= 5 ? 4 : 3]; | 1577 | { |
1585 | if (fhtype == 6) | 1578 | if (fh_type < 4) |
1586 | parent[2] = data[5]; | 1579 | return NULL; |
1587 | else | 1580 | |
1588 | parent[2] = 0; | 1581 | return reiserfs_get_dentry(sb, |
1589 | } | 1582 | (fh_type >= 5) ? fid->raw[3] : fid->raw[2], |
1590 | return sb->s_export_op->find_exported_dentry(sb, obj, | 1583 | (fh_type >= 5) ? fid->raw[4] : fid->raw[3], |
1591 | fhtype < 4 ? NULL : parent, | 1584 | (fh_type == 6) ? fid->raw[5] : 0); |
1592 | acceptable, context); | ||
1593 | } | 1585 | } |
1594 | 1586 | ||
1595 | int reiserfs_encode_fh(struct dentry *dentry, __u32 * data, int *lenp, | 1587 | int reiserfs_encode_fh(struct dentry *dentry, __u32 * data, int *lenp, |
diff --git a/fs/reiserfs/ioctl.c b/fs/reiserfs/ioctl.c index c438a8f83f26..e0f0f098a523 100644 --- a/fs/reiserfs/ioctl.c +++ b/fs/reiserfs/ioctl.c | |||
@@ -57,6 +57,9 @@ int reiserfs_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, | |||
57 | if (get_user(flags, (int __user *)arg)) | 57 | if (get_user(flags, (int __user *)arg)) |
58 | return -EFAULT; | 58 | return -EFAULT; |
59 | 59 | ||
60 | /* Is it quota file? Do not allow user to mess with it. */ | ||
61 | if (IS_NOQUOTA(inode)) | ||
62 | return -EPERM; | ||
60 | if (((flags ^ REISERFS_I(inode)-> | 63 | if (((flags ^ REISERFS_I(inode)-> |
61 | i_attrs) & (REISERFS_IMMUTABLE_FL | | 64 | i_attrs) & (REISERFS_IMMUTABLE_FL | |
62 | REISERFS_APPEND_FL)) | 65 | REISERFS_APPEND_FL)) |
diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c index 4cad9e75ef56..bb05a3e51b93 100644 --- a/fs/reiserfs/journal.c +++ b/fs/reiserfs/journal.c | |||
@@ -219,11 +219,12 @@ static void allocate_bitmap_nodes(struct super_block *p_s_sb) | |||
219 | } | 219 | } |
220 | } | 220 | } |
221 | 221 | ||
222 | static int set_bit_in_list_bitmap(struct super_block *p_s_sb, int block, | 222 | static int set_bit_in_list_bitmap(struct super_block *p_s_sb, |
223 | b_blocknr_t block, | ||
223 | struct reiserfs_list_bitmap *jb) | 224 | struct reiserfs_list_bitmap *jb) |
224 | { | 225 | { |
225 | int bmap_nr = block / (p_s_sb->s_blocksize << 3); | 226 | unsigned int bmap_nr = block / (p_s_sb->s_blocksize << 3); |
226 | int bit_nr = block % (p_s_sb->s_blocksize << 3); | 227 | unsigned int bit_nr = block % (p_s_sb->s_blocksize << 3); |
227 | 228 | ||
228 | if (!jb->bitmaps[bmap_nr]) { | 229 | if (!jb->bitmaps[bmap_nr]) { |
229 | jb->bitmaps[bmap_nr] = get_bitmap_node(p_s_sb); | 230 | jb->bitmaps[bmap_nr] = get_bitmap_node(p_s_sb); |
@@ -239,7 +240,7 @@ static void cleanup_bitmap_list(struct super_block *p_s_sb, | |||
239 | if (jb->bitmaps == NULL) | 240 | if (jb->bitmaps == NULL) |
240 | return; | 241 | return; |
241 | 242 | ||
242 | for (i = 0; i < SB_BMAP_NR(p_s_sb); i++) { | 243 | for (i = 0; i < reiserfs_bmap_count(p_s_sb); i++) { |
243 | if (jb->bitmaps[i]) { | 244 | if (jb->bitmaps[i]) { |
244 | free_bitmap_node(p_s_sb, jb->bitmaps[i]); | 245 | free_bitmap_node(p_s_sb, jb->bitmaps[i]); |
245 | jb->bitmaps[i] = NULL; | 246 | jb->bitmaps[i] = NULL; |
@@ -289,7 +290,7 @@ static int free_bitmap_nodes(struct super_block *p_s_sb) | |||
289 | */ | 290 | */ |
290 | int reiserfs_allocate_list_bitmaps(struct super_block *p_s_sb, | 291 | int reiserfs_allocate_list_bitmaps(struct super_block *p_s_sb, |
291 | struct reiserfs_list_bitmap *jb_array, | 292 | struct reiserfs_list_bitmap *jb_array, |
292 | int bmap_nr) | 293 | unsigned int bmap_nr) |
293 | { | 294 | { |
294 | int i; | 295 | int i; |
295 | int failed = 0; | 296 | int failed = 0; |
@@ -483,7 +484,7 @@ static inline struct reiserfs_journal_cnode *get_journal_hash_dev(struct | |||
483 | ** | 484 | ** |
484 | */ | 485 | */ |
485 | int reiserfs_in_journal(struct super_block *p_s_sb, | 486 | int reiserfs_in_journal(struct super_block *p_s_sb, |
486 | int bmap_nr, int bit_nr, int search_all, | 487 | unsigned int bmap_nr, int bit_nr, int search_all, |
487 | b_blocknr_t * next_zero_bit) | 488 | b_blocknr_t * next_zero_bit) |
488 | { | 489 | { |
489 | struct reiserfs_journal *journal = SB_JOURNAL(p_s_sb); | 490 | struct reiserfs_journal *journal = SB_JOURNAL(p_s_sb); |
@@ -1013,7 +1014,7 @@ static int flush_commit_list(struct super_block *s, | |||
1013 | struct reiserfs_journal_list *jl, int flushall) | 1014 | struct reiserfs_journal_list *jl, int flushall) |
1014 | { | 1015 | { |
1015 | int i; | 1016 | int i; |
1016 | int bn; | 1017 | b_blocknr_t bn; |
1017 | struct buffer_head *tbh = NULL; | 1018 | struct buffer_head *tbh = NULL; |
1018 | unsigned long trans_id = jl->j_trans_id; | 1019 | unsigned long trans_id = jl->j_trans_id; |
1019 | struct reiserfs_journal *journal = SB_JOURNAL(s); | 1020 | struct reiserfs_journal *journal = SB_JOURNAL(s); |
@@ -2307,8 +2308,9 @@ static int journal_read_transaction(struct super_block *p_s_sb, | |||
2307 | Right now it is only used from journal code. But later we might use it | 2308 | Right now it is only used from journal code. But later we might use it |
2308 | from other places. | 2309 | from other places. |
2309 | Note: Do not use journal_getblk/sb_getblk functions here! */ | 2310 | Note: Do not use journal_getblk/sb_getblk functions here! */ |
2310 | static struct buffer_head *reiserfs_breada(struct block_device *dev, int block, | 2311 | static struct buffer_head *reiserfs_breada(struct block_device *dev, |
2311 | int bufsize, unsigned int max_block) | 2312 | b_blocknr_t block, int bufsize, |
2313 | b_blocknr_t max_block) | ||
2312 | { | 2314 | { |
2313 | struct buffer_head *bhlist[BUFNR]; | 2315 | struct buffer_head *bhlist[BUFNR]; |
2314 | unsigned int blocks = BUFNR; | 2316 | unsigned int blocks = BUFNR; |
@@ -2732,7 +2734,7 @@ int journal_init(struct super_block *p_s_sb, const char *j_dev_name, | |||
2732 | journal->j_persistent_trans = 0; | 2734 | journal->j_persistent_trans = 0; |
2733 | if (reiserfs_allocate_list_bitmaps(p_s_sb, | 2735 | if (reiserfs_allocate_list_bitmaps(p_s_sb, |
2734 | journal->j_list_bitmap, | 2736 | journal->j_list_bitmap, |
2735 | SB_BMAP_NR(p_s_sb))) | 2737 | reiserfs_bmap_count(p_s_sb))) |
2736 | goto free_and_return; | 2738 | goto free_and_return; |
2737 | allocate_bitmap_nodes(p_s_sb); | 2739 | allocate_bitmap_nodes(p_s_sb); |
2738 | 2740 | ||
@@ -2740,7 +2742,7 @@ int journal_init(struct super_block *p_s_sb, const char *j_dev_name, | |||
2740 | SB_JOURNAL_1st_RESERVED_BLOCK(p_s_sb) = (old_format ? | 2742 | SB_JOURNAL_1st_RESERVED_BLOCK(p_s_sb) = (old_format ? |
2741 | REISERFS_OLD_DISK_OFFSET_IN_BYTES | 2743 | REISERFS_OLD_DISK_OFFSET_IN_BYTES |
2742 | / p_s_sb->s_blocksize + | 2744 | / p_s_sb->s_blocksize + |
2743 | SB_BMAP_NR(p_s_sb) + | 2745 | reiserfs_bmap_count(p_s_sb) + |
2744 | 1 : | 2746 | 1 : |
2745 | REISERFS_DISK_OFFSET_IN_BYTES / | 2747 | REISERFS_DISK_OFFSET_IN_BYTES / |
2746 | p_s_sb->s_blocksize + 2); | 2748 | p_s_sb->s_blocksize + 2); |
diff --git a/fs/reiserfs/prints.c b/fs/reiserfs/prints.c index bc808a91eeaa..5e7388b32d02 100644 --- a/fs/reiserfs/prints.c +++ b/fs/reiserfs/prints.c | |||
@@ -356,13 +356,11 @@ extern struct tree_balance *cur_tb; | |||
356 | void reiserfs_panic(struct super_block *sb, const char *fmt, ...) | 356 | void reiserfs_panic(struct super_block *sb, const char *fmt, ...) |
357 | { | 357 | { |
358 | do_reiserfs_warning(fmt); | 358 | do_reiserfs_warning(fmt); |
359 | printk(KERN_EMERG "REISERFS: panic (device %s): %s\n", | ||
360 | reiserfs_bdevname(sb), error_buf); | ||
361 | BUG(); | ||
362 | 359 | ||
363 | /* this is not actually called, but makes reiserfs_panic() "noreturn" */ | 360 | dump_stack(); |
364 | panic("REISERFS: panic (device %s): %s\n", | 361 | |
365 | reiserfs_bdevname(sb), error_buf); | 362 | panic(KERN_EMERG "REISERFS: panic (device %s): %s\n", |
363 | reiserfs_bdevname(sb), error_buf); | ||
366 | } | 364 | } |
367 | 365 | ||
368 | void reiserfs_abort(struct super_block *sb, int errno, const char *fmt, ...) | 366 | void reiserfs_abort(struct super_block *sb, int errno, const char *fmt, ...) |
diff --git a/fs/reiserfs/procfs.c b/fs/reiserfs/procfs.c index 9aa7a06e093f..001144621672 100644 --- a/fs/reiserfs/procfs.c +++ b/fs/reiserfs/procfs.c | |||
@@ -420,12 +420,6 @@ static void *r_start(struct seq_file *m, loff_t * pos) | |||
420 | return NULL; | 420 | return NULL; |
421 | 421 | ||
422 | up_write(&s->s_umount); | 422 | up_write(&s->s_umount); |
423 | |||
424 | if (de->deleted) { | ||
425 | deactivate_super(s); | ||
426 | return NULL; | ||
427 | } | ||
428 | |||
429 | return s; | 423 | return s; |
430 | } | 424 | } |
431 | 425 | ||
diff --git a/fs/reiserfs/resize.c b/fs/reiserfs/resize.c index 976cc7887a0d..f71c3948edef 100644 --- a/fs/reiserfs/resize.c +++ b/fs/reiserfs/resize.c | |||
@@ -61,7 +61,8 @@ int reiserfs_resize(struct super_block *s, unsigned long block_count_new) | |||
61 | } | 61 | } |
62 | 62 | ||
63 | /* count used bits in last bitmap block */ | 63 | /* count used bits in last bitmap block */ |
64 | block_r = SB_BLOCK_COUNT(s) - (SB_BMAP_NR(s) - 1) * s->s_blocksize * 8; | 64 | block_r = SB_BLOCK_COUNT(s) - |
65 | (reiserfs_bmap_count(s) - 1) * s->s_blocksize * 8; | ||
65 | 66 | ||
66 | /* count bitmap blocks in new fs */ | 67 | /* count bitmap blocks in new fs */ |
67 | bmap_nr_new = block_count_new / (s->s_blocksize * 8); | 68 | bmap_nr_new = block_count_new / (s->s_blocksize * 8); |
@@ -73,7 +74,7 @@ int reiserfs_resize(struct super_block *s, unsigned long block_count_new) | |||
73 | 74 | ||
74 | /* save old values */ | 75 | /* save old values */ |
75 | block_count = SB_BLOCK_COUNT(s); | 76 | block_count = SB_BLOCK_COUNT(s); |
76 | bmap_nr = SB_BMAP_NR(s); | 77 | bmap_nr = reiserfs_bmap_count(s); |
77 | 78 | ||
78 | /* resizing of reiserfs bitmaps (journal and real), if needed */ | 79 | /* resizing of reiserfs bitmaps (journal and real), if needed */ |
79 | if (bmap_nr_new > bmap_nr) { | 80 | if (bmap_nr_new > bmap_nr) { |
@@ -119,7 +120,7 @@ int reiserfs_resize(struct super_block *s, unsigned long block_count_new) | |||
119 | return -ENOMEM; | 120 | return -ENOMEM; |
120 | } | 121 | } |
121 | memset(bitmap, 0, | 122 | memset(bitmap, 0, |
122 | sizeof(struct reiserfs_bitmap_info) * SB_BMAP_NR(s)); | 123 | sizeof(struct reiserfs_bitmap_info) * bmap_nr_new); |
123 | for (i = 0; i < bmap_nr; i++) | 124 | for (i = 0; i < bmap_nr; i++) |
124 | bitmap[i] = old_bitmap[i]; | 125 | bitmap[i] = old_bitmap[i]; |
125 | 126 | ||
@@ -143,7 +144,6 @@ int reiserfs_resize(struct super_block *s, unsigned long block_count_new) | |||
143 | mark_buffer_dirty(bh); | 144 | mark_buffer_dirty(bh); |
144 | sync_dirty_buffer(bh); | 145 | sync_dirty_buffer(bh); |
145 | // update bitmap_info stuff | 146 | // update bitmap_info stuff |
146 | bitmap[i].first_zero_hint = 1; | ||
147 | bitmap[i].free_count = sb_blocksize(sb) * 8 - 1; | 147 | bitmap[i].free_count = sb_blocksize(sb) * 8 - 1; |
148 | brelse(bh); | 148 | brelse(bh); |
149 | } | 149 | } |
@@ -173,8 +173,6 @@ int reiserfs_resize(struct super_block *s, unsigned long block_count_new) | |||
173 | for (i = block_r; i < s->s_blocksize * 8; i++) | 173 | for (i = block_r; i < s->s_blocksize * 8; i++) |
174 | reiserfs_test_and_clear_le_bit(i, bh->b_data); | 174 | reiserfs_test_and_clear_le_bit(i, bh->b_data); |
175 | info->free_count += s->s_blocksize * 8 - block_r; | 175 | info->free_count += s->s_blocksize * 8 - block_r; |
176 | if (!info->first_zero_hint) | ||
177 | info->first_zero_hint = block_r; | ||
178 | 176 | ||
179 | journal_mark_dirty(&th, s, bh); | 177 | journal_mark_dirty(&th, s, bh); |
180 | brelse(bh); | 178 | brelse(bh); |
@@ -196,9 +194,6 @@ int reiserfs_resize(struct super_block *s, unsigned long block_count_new) | |||
196 | brelse(bh); | 194 | brelse(bh); |
197 | 195 | ||
198 | info->free_count -= s->s_blocksize * 8 - block_r_new; | 196 | info->free_count -= s->s_blocksize * 8 - block_r_new; |
199 | /* Extreme case where last bitmap is the only valid block in itself. */ | ||
200 | if (!info->free_count) | ||
201 | info->first_zero_hint = 0; | ||
202 | /* update super */ | 197 | /* update super */ |
203 | reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1); | 198 | reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1); |
204 | free_blocks = SB_FREE_BLOCKS(s); | 199 | free_blocks = SB_FREE_BLOCKS(s); |
@@ -206,7 +201,7 @@ int reiserfs_resize(struct super_block *s, unsigned long block_count_new) | |||
206 | free_blocks + (block_count_new - block_count - | 201 | free_blocks + (block_count_new - block_count - |
207 | (bmap_nr_new - bmap_nr))); | 202 | (bmap_nr_new - bmap_nr))); |
208 | PUT_SB_BLOCK_COUNT(s, block_count_new); | 203 | PUT_SB_BLOCK_COUNT(s, block_count_new); |
209 | PUT_SB_BMAP_NR(s, bmap_nr_new); | 204 | PUT_SB_BMAP_NR(s, bmap_would_wrap(bmap_nr_new) ? : bmap_nr_new); |
210 | s->s_dirt = 1; | 205 | s->s_dirt = 1; |
211 | 206 | ||
212 | journal_mark_dirty(&th, s, SB_BUFFER_WITH_SB(s)); | 207 | journal_mark_dirty(&th, s, SB_BUFFER_WITH_SB(s)); |
diff --git a/fs/reiserfs/stree.c b/fs/reiserfs/stree.c index 981027d1187b..d2db2417b2bd 100644 --- a/fs/reiserfs/stree.c +++ b/fs/reiserfs/stree.c | |||
@@ -559,7 +559,7 @@ static int is_tree_node(struct buffer_head *bh, int level) | |||
559 | /* The function is NOT SCHEDULE-SAFE! */ | 559 | /* The function is NOT SCHEDULE-SAFE! */ |
560 | static void search_by_key_reada(struct super_block *s, | 560 | static void search_by_key_reada(struct super_block *s, |
561 | struct buffer_head **bh, | 561 | struct buffer_head **bh, |
562 | unsigned long *b, int num) | 562 | b_blocknr_t *b, int num) |
563 | { | 563 | { |
564 | int i, j; | 564 | int i, j; |
565 | 565 | ||
@@ -611,7 +611,7 @@ int search_by_key(struct super_block *p_s_sb, const struct cpu_key *p_s_key, /* | |||
611 | DISK_LEAF_NODE_LEVEL */ | 611 | DISK_LEAF_NODE_LEVEL */ |
612 | ) | 612 | ) |
613 | { | 613 | { |
614 | int n_block_number; | 614 | b_blocknr_t n_block_number; |
615 | int expected_level; | 615 | int expected_level; |
616 | struct buffer_head *p_s_bh; | 616 | struct buffer_head *p_s_bh; |
617 | struct path_element *p_s_last_element; | 617 | struct path_element *p_s_last_element; |
@@ -619,7 +619,7 @@ int search_by_key(struct super_block *p_s_sb, const struct cpu_key *p_s_key, /* | |||
619 | int right_neighbor_of_leaf_node; | 619 | int right_neighbor_of_leaf_node; |
620 | int fs_gen; | 620 | int fs_gen; |
621 | struct buffer_head *reada_bh[SEARCH_BY_KEY_READA]; | 621 | struct buffer_head *reada_bh[SEARCH_BY_KEY_READA]; |
622 | unsigned long reada_blocks[SEARCH_BY_KEY_READA]; | 622 | b_blocknr_t reada_blocks[SEARCH_BY_KEY_READA]; |
623 | int reada_count = 0; | 623 | int reada_count = 0; |
624 | 624 | ||
625 | #ifdef CONFIG_REISERFS_CHECK | 625 | #ifdef CONFIG_REISERFS_CHECK |
@@ -1458,9 +1458,6 @@ static void unmap_buffers(struct page *page, loff_t pos) | |||
1458 | } | 1458 | } |
1459 | bh = next; | 1459 | bh = next; |
1460 | } while (bh != head); | 1460 | } while (bh != head); |
1461 | if (PAGE_SIZE == bh->b_size) { | ||
1462 | cancel_dirty_page(page, PAGE_CACHE_SIZE); | ||
1463 | } | ||
1464 | } | 1461 | } |
1465 | } | 1462 | } |
1466 | } | 1463 | } |
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index b82897ae090b..5cd85fe5df5d 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c | |||
@@ -319,7 +319,7 @@ static int finish_unfinished(struct super_block *s) | |||
319 | 319 | ||
320 | /* to protect file being unlinked from getting lost we "safe" link files | 320 | /* to protect file being unlinked from getting lost we "safe" link files |
321 | being unlinked. This link will be deleted in the same transaction with last | 321 | being unlinked. This link will be deleted in the same transaction with last |
322 | item of file. mounting the filesytem we scan all these links and remove | 322 | item of file. mounting the filesystem we scan all these links and remove |
323 | files which almost got lost */ | 323 | files which almost got lost */ |
324 | void add_save_link(struct reiserfs_transaction_handle *th, | 324 | void add_save_link(struct reiserfs_transaction_handle *th, |
325 | struct inode *inode, int truncate) | 325 | struct inode *inode, int truncate) |
@@ -661,11 +661,11 @@ static struct quotactl_ops reiserfs_qctl_operations = { | |||
661 | }; | 661 | }; |
662 | #endif | 662 | #endif |
663 | 663 | ||
664 | static struct export_operations reiserfs_export_ops = { | 664 | static const struct export_operations reiserfs_export_ops = { |
665 | .encode_fh = reiserfs_encode_fh, | 665 | .encode_fh = reiserfs_encode_fh, |
666 | .decode_fh = reiserfs_decode_fh, | 666 | .fh_to_dentry = reiserfs_fh_to_dentry, |
667 | .fh_to_parent = reiserfs_fh_to_parent, | ||
667 | .get_parent = reiserfs_get_parent, | 668 | .get_parent = reiserfs_get_parent, |
668 | .get_dentry = reiserfs_get_dentry, | ||
669 | }; | 669 | }; |
670 | 670 | ||
671 | /* this struct is used in reiserfs_getopt () for containing the value for those | 671 | /* this struct is used in reiserfs_getopt () for containing the value for those |
@@ -1725,6 +1725,21 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent) | |||
1725 | set_sb_umount_state(rs, REISERFS_ERROR_FS); | 1725 | set_sb_umount_state(rs, REISERFS_ERROR_FS); |
1726 | set_sb_fs_state(rs, 0); | 1726 | set_sb_fs_state(rs, 0); |
1727 | 1727 | ||
1728 | /* Clear out s_bmap_nr if it would wrap. We can handle this | ||
1729 | * case, but older revisions can't. This will cause the | ||
1730 | * file system to fail mount on those older implementations, | ||
1731 | * avoiding corruption. -jeffm */ | ||
1732 | if (bmap_would_wrap(reiserfs_bmap_count(s)) && | ||
1733 | sb_bmap_nr(rs) != 0) { | ||
1734 | reiserfs_warning(s, "super-2030: This file system " | ||
1735 | "claims to use %u bitmap blocks in " | ||
1736 | "its super block, but requires %u. " | ||
1737 | "Clearing to zero.", sb_bmap_nr(rs), | ||
1738 | reiserfs_bmap_count(s)); | ||
1739 | |||
1740 | set_sb_bmap_nr(rs, 0); | ||
1741 | } | ||
1742 | |||
1728 | if (old_format_only(s)) { | 1743 | if (old_format_only(s)) { |
1729 | /* filesystem of format 3.5 either with standard or non-standard | 1744 | /* filesystem of format 3.5 either with standard or non-standard |
1730 | journal */ | 1745 | journal */ |
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c index fab4b9b2664f..1597f6b649e0 100644 --- a/fs/reiserfs/xattr.c +++ b/fs/reiserfs/xattr.c | |||
@@ -484,7 +484,7 @@ reiserfs_xattr_set(struct inode *inode, const char *name, const void *buffer, | |||
484 | /* Resize it so we're ok to write there */ | 484 | /* Resize it so we're ok to write there */ |
485 | newattrs.ia_size = buffer_size; | 485 | newattrs.ia_size = buffer_size; |
486 | newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME; | 486 | newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME; |
487 | mutex_lock(&xinode->i_mutex); | 487 | mutex_lock_nested(&xinode->i_mutex, I_MUTEX_XATTR); |
488 | err = notify_change(fp->f_path.dentry, &newattrs); | 488 | err = notify_change(fp->f_path.dentry, &newattrs); |
489 | if (err) | 489 | if (err) |
490 | goto out_filp; | 490 | goto out_filp; |
@@ -1223,7 +1223,8 @@ int reiserfs_xattr_init(struct super_block *s, int mount_flags) | |||
1223 | if (!IS_ERR(dentry)) { | 1223 | if (!IS_ERR(dentry)) { |
1224 | if (!(mount_flags & MS_RDONLY) && !dentry->d_inode) { | 1224 | if (!(mount_flags & MS_RDONLY) && !dentry->d_inode) { |
1225 | struct inode *inode = dentry->d_parent->d_inode; | 1225 | struct inode *inode = dentry->d_parent->d_inode; |
1226 | mutex_lock(&inode->i_mutex); | 1226 | mutex_lock_nested(&inode->i_mutex, |
1227 | I_MUTEX_XATTR); | ||
1227 | err = inode->i_op->mkdir(inode, dentry, 0700); | 1228 | err = inode->i_op->mkdir(inode, dentry, 0700); |
1228 | mutex_unlock(&inode->i_mutex); | 1229 | mutex_unlock(&inode->i_mutex); |
1229 | if (err) { | 1230 | if (err) { |
diff --git a/fs/select.c b/fs/select.c index 7dede89658f5..47f47925aea2 100644 --- a/fs/select.c +++ b/fs/select.c | |||
@@ -177,11 +177,6 @@ get_max: | |||
177 | return max; | 177 | return max; |
178 | } | 178 | } |
179 | 179 | ||
180 | #define BIT(i) (1UL << ((i)&(__NFDBITS-1))) | ||
181 | #define MEM(i,m) ((m)+(unsigned)(i)/__NFDBITS) | ||
182 | #define ISSET(i,m) (((i)&*(m)) != 0) | ||
183 | #define SET(i,m) (*(m) |= (i)) | ||
184 | |||
185 | #define POLLIN_SET (POLLRDNORM | POLLRDBAND | POLLIN | POLLHUP | POLLERR) | 180 | #define POLLIN_SET (POLLRDNORM | POLLRDBAND | POLLIN | POLLHUP | POLLERR) |
186 | #define POLLOUT_SET (POLLWRBAND | POLLWRNORM | POLLOUT | POLLERR) | 181 | #define POLLOUT_SET (POLLWRBAND | POLLWRNORM | POLLOUT | POLLERR) |
187 | #define POLLEX_SET (POLLPRI) | 182 | #define POLLEX_SET (POLLPRI) |
diff --git a/fs/smbfs/file.c b/fs/smbfs/file.c index f5d14cebc75a..efbe29af3d7a 100644 --- a/fs/smbfs/file.c +++ b/fs/smbfs/file.c | |||
@@ -234,7 +234,7 @@ smb_file_aio_read(struct kiocb *iocb, const struct iovec *iov, | |||
234 | 234 | ||
235 | VERBOSE("before read, size=%ld, flags=%x, atime=%ld\n", | 235 | VERBOSE("before read, size=%ld, flags=%x, atime=%ld\n", |
236 | (long)dentry->d_inode->i_size, | 236 | (long)dentry->d_inode->i_size, |
237 | dentry->d_inode->i_flags, dentry->d_inode->i_atime); | 237 | dentry->d_inode->i_flags, dentry->d_inode->i_atime.tv_sec); |
238 | 238 | ||
239 | status = generic_file_aio_read(iocb, iov, nr_segs, pos); | 239 | status = generic_file_aio_read(iocb, iov, nr_segs, pos); |
240 | out: | 240 | out: |
@@ -269,7 +269,7 @@ smb_file_splice_read(struct file *file, loff_t *ppos, | |||
269 | struct dentry *dentry = file->f_path.dentry; | 269 | struct dentry *dentry = file->f_path.dentry; |
270 | ssize_t status; | 270 | ssize_t status; |
271 | 271 | ||
272 | VERBOSE("file %s/%s, pos=%Ld, count=%d\n", | 272 | VERBOSE("file %s/%s, pos=%Ld, count=%lu\n", |
273 | DENTRY_PATH(dentry), *ppos, count); | 273 | DENTRY_PATH(dentry), *ppos, count); |
274 | 274 | ||
275 | status = smb_revalidate_inode(dentry); | 275 | status = smb_revalidate_inode(dentry); |
@@ -363,7 +363,8 @@ smb_file_aio_write(struct kiocb *iocb, const struct iovec *iov, | |||
363 | result = generic_file_aio_write(iocb, iov, nr_segs, pos); | 363 | result = generic_file_aio_write(iocb, iov, nr_segs, pos); |
364 | VERBOSE("pos=%ld, size=%ld, mtime=%ld, atime=%ld\n", | 364 | VERBOSE("pos=%ld, size=%ld, mtime=%ld, atime=%ld\n", |
365 | (long) file->f_pos, (long) dentry->d_inode->i_size, | 365 | (long) file->f_pos, (long) dentry->d_inode->i_size, |
366 | dentry->d_inode->i_mtime, dentry->d_inode->i_atime); | 366 | dentry->d_inode->i_mtime.tv_sec, |
367 | dentry->d_inode->i_atime.tv_sec); | ||
367 | } | 368 | } |
368 | out: | 369 | out: |
369 | return result; | 370 | return result; |
diff --git a/fs/smbfs/inode.c b/fs/smbfs/inode.c index ab517755ece0..9416ead0c7aa 100644 --- a/fs/smbfs/inode.c +++ b/fs/smbfs/inode.c | |||
@@ -536,7 +536,7 @@ static int smb_fill_super(struct super_block *sb, void *raw_data, int silent) | |||
536 | 536 | ||
537 | /* Allocate the global temp buffer and some superblock helper structs */ | 537 | /* Allocate the global temp buffer and some superblock helper structs */ |
538 | /* FIXME: move these to the smb_sb_info struct */ | 538 | /* FIXME: move these to the smb_sb_info struct */ |
539 | VERBOSE("alloc chunk = %d\n", sizeof(struct smb_ops) + | 539 | VERBOSE("alloc chunk = %lu\n", sizeof(struct smb_ops) + |
540 | sizeof(struct smb_mount_data_kernel)); | 540 | sizeof(struct smb_mount_data_kernel)); |
541 | mem = kmalloc(sizeof(struct smb_ops) + | 541 | mem = kmalloc(sizeof(struct smb_ops) + |
542 | sizeof(struct smb_mount_data_kernel), GFP_KERNEL); | 542 | sizeof(struct smb_mount_data_kernel), GFP_KERNEL); |
diff --git a/fs/smbfs/proc.c b/fs/smbfs/proc.c index feac46050619..d517a27b7f4b 100644 --- a/fs/smbfs/proc.c +++ b/fs/smbfs/proc.c | |||
@@ -2593,7 +2593,7 @@ smb_proc_getattr_ff(struct smb_sb_info *server, struct dentry *dentry, | |||
2593 | fattr->f_mtime.tv_sec = date_dos2unix(server, date, time); | 2593 | fattr->f_mtime.tv_sec = date_dos2unix(server, date, time); |
2594 | fattr->f_mtime.tv_nsec = 0; | 2594 | fattr->f_mtime.tv_nsec = 0; |
2595 | VERBOSE("name=%s, date=%x, time=%x, mtime=%ld\n", | 2595 | VERBOSE("name=%s, date=%x, time=%x, mtime=%ld\n", |
2596 | mask, date, time, fattr->f_mtime); | 2596 | mask, date, time, fattr->f_mtime.tv_sec); |
2597 | fattr->f_size = DVAL(req->rq_data, 12); | 2597 | fattr->f_size = DVAL(req->rq_data, 12); |
2598 | /* ULONG allocation size */ | 2598 | /* ULONG allocation size */ |
2599 | fattr->attr = WVAL(req->rq_data, 20); | 2599 | fattr->attr = WVAL(req->rq_data, 20); |
diff --git a/fs/smbfs/smbiod.c b/fs/smbfs/smbiod.c index 283c5720c9de..fae8e85af0ed 100644 --- a/fs/smbfs/smbiod.c +++ b/fs/smbfs/smbiod.c | |||
@@ -227,7 +227,7 @@ int smbiod_retry(struct smb_sb_info *server) | |||
227 | printk(KERN_ERR "smb_retry: signal failed [%d]\n", result); | 227 | printk(KERN_ERR "smb_retry: signal failed [%d]\n", result); |
228 | goto out; | 228 | goto out; |
229 | } | 229 | } |
230 | VERBOSE("signalled pid %d\n", pid); | 230 | VERBOSE("signalled pid %d\n", pid_nr(pid)); |
231 | 231 | ||
232 | /* FIXME: The retried requests should perhaps get a "time boost". */ | 232 | /* FIXME: The retried requests should perhaps get a "time boost". */ |
233 | 233 | ||
diff --git a/fs/super.c b/fs/super.c index 1bfcca2104be..ceaf2e3d594c 100644 --- a/fs/super.c +++ b/fs/super.c | |||
@@ -15,7 +15,7 @@ | |||
15 | * Added kerneld support: Jacques Gelinas and Bjorn Ekwall | 15 | * Added kerneld support: Jacques Gelinas and Bjorn Ekwall |
16 | * Added change_root: Werner Almesberger & Hans Lermen, Feb '96 | 16 | * Added change_root: Werner Almesberger & Hans Lermen, Feb '96 |
17 | * Added options to /proc/mounts: | 17 | * Added options to /proc/mounts: |
18 | * Torbjörn Lindh (torbjorn.lindh@gopta.se), April 14, 1996. | 18 | * Torbjörn Lindh (torbjorn.lindh@gopta.se), April 14, 1996. |
19 | * Added devfs support: Richard Gooch <rgooch@atnf.csiro.au>, 13-JAN-1998 | 19 | * Added devfs support: Richard Gooch <rgooch@atnf.csiro.au>, 13-JAN-1998 |
20 | * Heavily rewritten for 'one fs - one tree' dcache architecture. AV, Mar 2000 | 20 | * Heavily rewritten for 'one fs - one tree' dcache architecture. AV, Mar 2000 |
21 | */ | 21 | */ |
@@ -40,10 +40,6 @@ | |||
40 | #include <asm/uaccess.h> | 40 | #include <asm/uaccess.h> |
41 | 41 | ||
42 | 42 | ||
43 | void get_filesystem(struct file_system_type *fs); | ||
44 | void put_filesystem(struct file_system_type *fs); | ||
45 | struct file_system_type *get_fs_type(const char *name); | ||
46 | |||
47 | LIST_HEAD(super_blocks); | 43 | LIST_HEAD(super_blocks); |
48 | DEFINE_SPINLOCK(sb_lock); | 44 | DEFINE_SPINLOCK(sb_lock); |
49 | 45 | ||
@@ -336,21 +332,21 @@ struct super_block *sget(struct file_system_type *type, | |||
336 | void *data) | 332 | void *data) |
337 | { | 333 | { |
338 | struct super_block *s = NULL; | 334 | struct super_block *s = NULL; |
339 | struct list_head *p; | 335 | struct super_block *old; |
340 | int err; | 336 | int err; |
341 | 337 | ||
342 | retry: | 338 | retry: |
343 | spin_lock(&sb_lock); | 339 | spin_lock(&sb_lock); |
344 | if (test) list_for_each(p, &type->fs_supers) { | 340 | if (test) { |
345 | struct super_block *old; | 341 | list_for_each_entry(old, &type->fs_supers, s_instances) { |
346 | old = list_entry(p, struct super_block, s_instances); | 342 | if (!test(old, data)) |
347 | if (!test(old, data)) | 343 | continue; |
348 | continue; | 344 | if (!grab_super(old)) |
349 | if (!grab_super(old)) | 345 | goto retry; |
350 | goto retry; | 346 | if (s) |
351 | if (s) | 347 | destroy_super(s); |
352 | destroy_super(s); | 348 | return old; |
353 | return old; | 349 | } |
354 | } | 350 | } |
355 | if (!s) { | 351 | if (!s) { |
356 | spin_unlock(&sb_lock); | 352 | spin_unlock(&sb_lock); |
@@ -421,7 +417,7 @@ restart: | |||
421 | } | 417 | } |
422 | 418 | ||
423 | /* | 419 | /* |
424 | * Call the ->sync_fs super_op against all filesytems which are r/w and | 420 | * Call the ->sync_fs super_op against all filesystems which are r/w and |
425 | * which implement it. | 421 | * which implement it. |
426 | * | 422 | * |
427 | * This operation is careful to avoid the livelock which could easily happen | 423 | * This operation is careful to avoid the livelock which could easily happen |
@@ -429,7 +425,7 @@ restart: | |||
429 | * is used only here. We set it against all filesystems and then clear it as | 425 | * is used only here. We set it against all filesystems and then clear it as |
430 | * we sync them. So redirtied filesystems are skipped. | 426 | * we sync them. So redirtied filesystems are skipped. |
431 | * | 427 | * |
432 | * But if process A is currently running sync_filesytems and then process B | 428 | * But if process A is currently running sync_filesystems and then process B |
433 | * calls sync_filesystems as well, process B will set all the s_need_sync_fs | 429 | * calls sync_filesystems as well, process B will set all the s_need_sync_fs |
434 | * flags again, which will cause process A to resync everything. Fix that with | 430 | * flags again, which will cause process A to resync everything. Fix that with |
435 | * a local mutex. | 431 | * a local mutex. |
@@ -948,9 +944,9 @@ do_kern_mount(const char *fstype, int flags, const char *name, void *data) | |||
948 | return mnt; | 944 | return mnt; |
949 | } | 945 | } |
950 | 946 | ||
951 | struct vfsmount *kern_mount(struct file_system_type *type) | 947 | struct vfsmount *kern_mount_data(struct file_system_type *type, void *data) |
952 | { | 948 | { |
953 | return vfs_kern_mount(type, 0, type->name, NULL); | 949 | return vfs_kern_mount(type, MS_KERNMOUNT, type->name, data); |
954 | } | 950 | } |
955 | 951 | ||
956 | EXPORT_SYMBOL(kern_mount); | 952 | EXPORT_SYMBOL_GPL(kern_mount_data); |
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 7a8ce9e98b32..337162935d21 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c | |||
@@ -132,7 +132,7 @@ struct dentry *sysfs_get_dentry(struct sysfs_dirent *sd) | |||
132 | * RETURNS: | 132 | * RETURNS: |
133 | * Pointer to @sd on success, NULL on failure. | 133 | * Pointer to @sd on success, NULL on failure. |
134 | */ | 134 | */ |
135 | struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd) | 135 | static struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd) |
136 | { | 136 | { |
137 | if (unlikely(!sd)) | 137 | if (unlikely(!sd)) |
138 | return NULL; | 138 | return NULL; |
@@ -161,7 +161,7 @@ struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd) | |||
161 | * Put an active reference to @sd. This function is noop if @sd | 161 | * Put an active reference to @sd. This function is noop if @sd |
162 | * is NULL. | 162 | * is NULL. |
163 | */ | 163 | */ |
164 | void sysfs_put_active(struct sysfs_dirent *sd) | 164 | static void sysfs_put_active(struct sysfs_dirent *sd) |
165 | { | 165 | { |
166 | struct completion *cmpl; | 166 | struct completion *cmpl; |
167 | int v; | 167 | int v; |
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index d3be1e7fb48b..4045bdcc4b33 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c | |||
@@ -119,7 +119,11 @@ static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer | |||
119 | 119 | ||
120 | sysfs_put_active_two(attr_sd); | 120 | sysfs_put_active_two(attr_sd); |
121 | 121 | ||
122 | BUG_ON(count > (ssize_t)PAGE_SIZE); | 122 | /* |
123 | * The code works fine with PAGE_SIZE return but it's likely to | ||
124 | * indicate truncated result or overflow in normal use cases. | ||
125 | */ | ||
126 | BUG_ON(count >= (ssize_t)PAGE_SIZE); | ||
123 | if (count >= 0) { | 127 | if (count >= 0) { |
124 | buffer->needs_read_fill = 0; | 128 | buffer->needs_read_fill = 0; |
125 | buffer->count = count; | 129 | buffer->count = count; |
@@ -540,7 +544,7 @@ int sysfs_add_file(struct sysfs_dirent *dir_sd, const struct attribute *attr, | |||
540 | /** | 544 | /** |
541 | * sysfs_create_file - create an attribute file for an object. | 545 | * sysfs_create_file - create an attribute file for an object. |
542 | * @kobj: object we're creating for. | 546 | * @kobj: object we're creating for. |
543 | * @attr: atrribute descriptor. | 547 | * @attr: attribute descriptor. |
544 | */ | 548 | */ |
545 | 549 | ||
546 | int sysfs_create_file(struct kobject * kobj, const struct attribute * attr) | 550 | int sysfs_create_file(struct kobject * kobj, const struct attribute * attr) |
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index f8417988f6b0..ff17f8da9b43 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h | |||
@@ -103,8 +103,6 @@ extern const struct file_operations sysfs_dir_operations; | |||
103 | extern const struct inode_operations sysfs_dir_inode_operations; | 103 | extern const struct inode_operations sysfs_dir_inode_operations; |
104 | 104 | ||
105 | struct dentry *sysfs_get_dentry(struct sysfs_dirent *sd); | 105 | struct dentry *sysfs_get_dentry(struct sysfs_dirent *sd); |
106 | struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd); | ||
107 | void sysfs_put_active(struct sysfs_dirent *sd); | ||
108 | struct sysfs_dirent *sysfs_get_active_two(struct sysfs_dirent *sd); | 106 | struct sysfs_dirent *sysfs_get_active_two(struct sysfs_dirent *sd); |
109 | void sysfs_put_active_two(struct sysfs_dirent *sd); | 107 | void sysfs_put_active_two(struct sysfs_dirent *sd); |
110 | void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt, | 108 | void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt, |
diff --git a/fs/ufs/dir.c b/fs/ufs/dir.c index 30f8c2bb0c3e..aaf2878305ce 100644 --- a/fs/ufs/dir.c +++ b/fs/ufs/dir.c | |||
@@ -179,7 +179,7 @@ bad_entry: | |||
179 | goto fail; | 179 | goto fail; |
180 | Eend: | 180 | Eend: |
181 | p = (struct ufs_dir_entry *)(kaddr + offs); | 181 | p = (struct ufs_dir_entry *)(kaddr + offs); |
182 | ufs_error (sb, "ext2_check_page", | 182 | ufs_error(sb, __FUNCTION__, |
183 | "entry in directory #%lu spans the page boundary" | 183 | "entry in directory #%lu spans the page boundary" |
184 | "offset=%lu", | 184 | "offset=%lu", |
185 | dir->i_ino, (page->index<<PAGE_CACHE_SHIFT)+offs); | 185 | dir->i_ino, (page->index<<PAGE_CACHE_SHIFT)+offs); |
diff --git a/fs/ufs/super.c b/fs/ufs/super.c index 584cf12cc40f..0072cb33ebec 100644 --- a/fs/ufs/super.c +++ b/fs/ufs/super.c | |||
@@ -755,13 +755,13 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent) | |||
755 | break; | 755 | break; |
756 | 756 | ||
757 | case UFS_MOUNT_UFSTYPE_NEXTSTEP: | 757 | case UFS_MOUNT_UFSTYPE_NEXTSTEP: |
758 | /*TODO: check may be we need set special dir block size?*/ | ||
759 | UFSD("ufstype=nextstep\n"); | 758 | UFSD("ufstype=nextstep\n"); |
760 | uspi->s_fsize = block_size = 1024; | 759 | uspi->s_fsize = block_size = 1024; |
761 | uspi->s_fmask = ~(1024 - 1); | 760 | uspi->s_fmask = ~(1024 - 1); |
762 | uspi->s_fshift = 10; | 761 | uspi->s_fshift = 10; |
763 | uspi->s_sbsize = super_block_size = 2048; | 762 | uspi->s_sbsize = super_block_size = 2048; |
764 | uspi->s_sbbase = 0; | 763 | uspi->s_sbbase = 0; |
764 | uspi->s_dirblksize = 1024; | ||
765 | flags |= UFS_DE_OLD | UFS_UID_OLD | UFS_ST_OLD | UFS_CG_OLD; | 765 | flags |= UFS_DE_OLD | UFS_UID_OLD | UFS_ST_OLD | UFS_CG_OLD; |
766 | if (!(sb->s_flags & MS_RDONLY)) { | 766 | if (!(sb->s_flags & MS_RDONLY)) { |
767 | if (!silent) | 767 | if (!silent) |
@@ -771,13 +771,13 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent) | |||
771 | break; | 771 | break; |
772 | 772 | ||
773 | case UFS_MOUNT_UFSTYPE_NEXTSTEP_CD: | 773 | case UFS_MOUNT_UFSTYPE_NEXTSTEP_CD: |
774 | /*TODO: check may be we need set special dir block size?*/ | ||
775 | UFSD("ufstype=nextstep-cd\n"); | 774 | UFSD("ufstype=nextstep-cd\n"); |
776 | uspi->s_fsize = block_size = 2048; | 775 | uspi->s_fsize = block_size = 2048; |
777 | uspi->s_fmask = ~(2048 - 1); | 776 | uspi->s_fmask = ~(2048 - 1); |
778 | uspi->s_fshift = 11; | 777 | uspi->s_fshift = 11; |
779 | uspi->s_sbsize = super_block_size = 2048; | 778 | uspi->s_sbsize = super_block_size = 2048; |
780 | uspi->s_sbbase = 0; | 779 | uspi->s_sbbase = 0; |
780 | uspi->s_dirblksize = 1024; | ||
781 | flags |= UFS_DE_OLD | UFS_UID_OLD | UFS_ST_OLD | UFS_CG_OLD; | 781 | flags |= UFS_DE_OLD | UFS_UID_OLD | UFS_ST_OLD | UFS_CG_OLD; |
782 | if (!(sb->s_flags & MS_RDONLY)) { | 782 | if (!(sb->s_flags & MS_RDONLY)) { |
783 | if (!silent) | 783 | if (!silent) |
@@ -933,20 +933,19 @@ magic_found: | |||
933 | goto again; | 933 | goto again; |
934 | } | 934 | } |
935 | 935 | ||
936 | /* Set sbi->s_flags here, used by ufs_get_fs_state() below */ | 936 | sbi->s_flags = flags;/*after that line some functions use s_flags*/ |
937 | sbi->s_flags = flags; | ||
938 | ufs_print_super_stuff(sb, usb1, usb2, usb3); | 937 | ufs_print_super_stuff(sb, usb1, usb2, usb3); |
939 | 938 | ||
940 | /* | 939 | /* |
941 | * Check, if file system was correctly unmounted. | 940 | * Check, if file system was correctly unmounted. |
942 | * If not, make it read only. | 941 | * If not, make it read only. |
943 | */ | 942 | */ |
944 | if ((((flags & UFS_ST_MASK) == UFS_ST_44BSD) || | 943 | if (((flags & UFS_ST_MASK) == UFS_ST_44BSD) || |
945 | ((flags & UFS_ST_MASK) == UFS_ST_OLD) || | 944 | ((flags & UFS_ST_MASK) == UFS_ST_OLD) || |
946 | ((flags & UFS_ST_MASK) == UFS_ST_SUN) || | 945 | (((flags & UFS_ST_MASK) == UFS_ST_SUN || |
947 | ((flags & UFS_ST_MASK) == UFS_ST_SUNOS) || | 946 | (flags & UFS_ST_MASK) == UFS_ST_SUNOS || |
948 | ((flags & UFS_ST_MASK) == UFS_ST_SUNx86)) && | 947 | (flags & UFS_ST_MASK) == UFS_ST_SUNx86) && |
949 | (ufs_get_fs_state(sb, usb1, usb3) == (UFS_FSOK - fs32_to_cpu(sb, usb1->fs_time)))) { | 948 | (ufs_get_fs_state(sb, usb1, usb3) == (UFS_FSOK - fs32_to_cpu(sb, usb1->fs_time))))) { |
950 | switch(usb1->fs_clean) { | 949 | switch(usb1->fs_clean) { |
951 | case UFS_FSCLEAN: | 950 | case UFS_FSCLEAN: |
952 | UFSD("fs is clean\n"); | 951 | UFSD("fs is clean\n"); |
diff --git a/fs/xattr.c b/fs/xattr.c index a44fd92caca3..6645b7313b33 100644 --- a/fs/xattr.c +++ b/fs/xattr.c | |||
@@ -267,7 +267,7 @@ sys_fsetxattr(int fd, char __user *name, void __user *value, | |||
267 | if (!f) | 267 | if (!f) |
268 | return error; | 268 | return error; |
269 | dentry = f->f_path.dentry; | 269 | dentry = f->f_path.dentry; |
270 | audit_inode(NULL, dentry->d_inode); | 270 | audit_inode(NULL, dentry); |
271 | error = setxattr(dentry, name, value, size, flags); | 271 | error = setxattr(dentry, name, value, size, flags); |
272 | fput(f); | 272 | fput(f); |
273 | return error; | 273 | return error; |
@@ -349,7 +349,7 @@ sys_fgetxattr(int fd, char __user *name, void __user *value, size_t size) | |||
349 | f = fget(fd); | 349 | f = fget(fd); |
350 | if (!f) | 350 | if (!f) |
351 | return error; | 351 | return error; |
352 | audit_inode(NULL, f->f_path.dentry->d_inode); | 352 | audit_inode(NULL, f->f_path.dentry); |
353 | error = getxattr(f->f_path.dentry, name, value, size); | 353 | error = getxattr(f->f_path.dentry, name, value, size); |
354 | fput(f); | 354 | fput(f); |
355 | return error; | 355 | return error; |
@@ -422,7 +422,7 @@ sys_flistxattr(int fd, char __user *list, size_t size) | |||
422 | f = fget(fd); | 422 | f = fget(fd); |
423 | if (!f) | 423 | if (!f) |
424 | return error; | 424 | return error; |
425 | audit_inode(NULL, f->f_path.dentry->d_inode); | 425 | audit_inode(NULL, f->f_path.dentry); |
426 | error = listxattr(f->f_path.dentry, list, size); | 426 | error = listxattr(f->f_path.dentry, list, size); |
427 | fput(f); | 427 | fput(f); |
428 | return error; | 428 | return error; |
@@ -485,7 +485,7 @@ sys_fremovexattr(int fd, char __user *name) | |||
485 | if (!f) | 485 | if (!f) |
486 | return error; | 486 | return error; |
487 | dentry = f->f_path.dentry; | 487 | dentry = f->f_path.dentry; |
488 | audit_inode(NULL, dentry->d_inode); | 488 | audit_inode(NULL, dentry); |
489 | error = removexattr(dentry, name); | 489 | error = removexattr(dentry, name); |
490 | fput(f); | 490 | fput(f); |
491 | return error; | 491 | return error; |
diff --git a/fs/xfs/linux-2.6/xfs_export.c b/fs/xfs/linux-2.6/xfs_export.c index 3586c7a28d2c..15bd4948832c 100644 --- a/fs/xfs/linux-2.6/xfs_export.c +++ b/fs/xfs/linux-2.6/xfs_export.c | |||
@@ -33,62 +33,25 @@ | |||
33 | static struct dentry dotdot = { .d_name.name = "..", .d_name.len = 2, }; | 33 | static struct dentry dotdot = { .d_name.name = "..", .d_name.len = 2, }; |
34 | 34 | ||
35 | /* | 35 | /* |
36 | * XFS encodes and decodes the fileid portion of NFS filehandles | 36 | * Note that we only accept fileids which are long enough rather than allow |
37 | * itself instead of letting the generic NFS code do it. This | 37 | * the parent generation number to default to zero. XFS considers zero a |
38 | * allows filesystems with 64 bit inode numbers to be exported. | 38 | * valid generation number not an invalid/wildcard value. |
39 | * | ||
40 | * Note that a side effect is that xfs_vget() won't be passed a | ||
41 | * zero inode/generation pair under normal circumstances. As | ||
42 | * however a malicious client could send us such data, the check | ||
43 | * remains in that code. | ||
44 | */ | 39 | */ |
45 | 40 | static int xfs_fileid_length(int fileid_type) | |
46 | STATIC struct dentry * | ||
47 | xfs_fs_decode_fh( | ||
48 | struct super_block *sb, | ||
49 | __u32 *fh, | ||
50 | int fh_len, | ||
51 | int fileid_type, | ||
52 | int (*acceptable)( | ||
53 | void *context, | ||
54 | struct dentry *de), | ||
55 | void *context) | ||
56 | { | 41 | { |
57 | xfs_fid_t ifid; | 42 | switch (fileid_type) { |
58 | xfs_fid_t pfid; | 43 | case FILEID_INO32_GEN: |
59 | void *parent = NULL; | 44 | return 2; |
60 | int is64 = 0; | 45 | case FILEID_INO32_GEN_PARENT: |
61 | __u32 *p = fh; | 46 | return 4; |
62 | 47 | case FILEID_INO32_GEN | XFS_FILEID_TYPE_64FLAG: | |
63 | #if XFS_BIG_INUMS | 48 | return 3; |
64 | is64 = (fileid_type & XFS_FILEID_TYPE_64FLAG); | 49 | case FILEID_INO32_GEN_PARENT | XFS_FILEID_TYPE_64FLAG: |
65 | fileid_type &= ~XFS_FILEID_TYPE_64FLAG; | 50 | return 6; |
66 | #endif | ||
67 | |||
68 | /* | ||
69 | * Note that we only accept fileids which are long enough | ||
70 | * rather than allow the parent generation number to default | ||
71 | * to zero. XFS considers zero a valid generation number not | ||
72 | * an invalid/wildcard value. There's little point printk'ing | ||
73 | * a warning here as we don't have the client information | ||
74 | * which would make such a warning useful. | ||
75 | */ | ||
76 | if (fileid_type > 2 || | ||
77 | fh_len < xfs_fileid_length((fileid_type == 2), is64)) | ||
78 | return NULL; | ||
79 | |||
80 | p = xfs_fileid_decode_fid2(p, &ifid, is64); | ||
81 | |||
82 | if (fileid_type == 2) { | ||
83 | p = xfs_fileid_decode_fid2(p, &pfid, is64); | ||
84 | parent = &pfid; | ||
85 | } | 51 | } |
86 | 52 | return 255; /* invalid */ | |
87 | fh = (__u32 *)&ifid; | ||
88 | return sb->s_export_op->find_exported_dentry(sb, fh, parent, acceptable, context); | ||
89 | } | 53 | } |
90 | 54 | ||
91 | |||
92 | STATIC int | 55 | STATIC int |
93 | xfs_fs_encode_fh( | 56 | xfs_fs_encode_fh( |
94 | struct dentry *dentry, | 57 | struct dentry *dentry, |
@@ -96,21 +59,21 @@ xfs_fs_encode_fh( | |||
96 | int *max_len, | 59 | int *max_len, |
97 | int connectable) | 60 | int connectable) |
98 | { | 61 | { |
62 | struct fid *fid = (struct fid *)fh; | ||
63 | struct xfs_fid64 *fid64 = (struct xfs_fid64 *)fh; | ||
99 | struct inode *inode = dentry->d_inode; | 64 | struct inode *inode = dentry->d_inode; |
100 | int type = 1; | 65 | int fileid_type; |
101 | __u32 *p = fh; | ||
102 | int len; | 66 | int len; |
103 | int is64 = 0; | ||
104 | #if XFS_BIG_INUMS | ||
105 | if (!(XFS_M(inode->i_sb)->m_flags & XFS_MOUNT_SMALL_INUMS)) { | ||
106 | /* filesystem may contain 64bit inode numbers */ | ||
107 | is64 = XFS_FILEID_TYPE_64FLAG; | ||
108 | } | ||
109 | #endif | ||
110 | 67 | ||
111 | /* Directories don't need their parent encoded, they have ".." */ | 68 | /* Directories don't need their parent encoded, they have ".." */ |
112 | if (S_ISDIR(inode->i_mode)) | 69 | if (S_ISDIR(inode->i_mode)) |
113 | connectable = 0; | 70 | fileid_type = FILEID_INO32_GEN; |
71 | else | ||
72 | fileid_type = FILEID_INO32_GEN_PARENT; | ||
73 | |||
74 | /* filesystem may contain 64bit inode numbers */ | ||
75 | if (!(XFS_M(inode->i_sb)->m_flags & XFS_MOUNT_SMALL_INUMS)) | ||
76 | fileid_type |= XFS_FILEID_TYPE_64FLAG; | ||
114 | 77 | ||
115 | /* | 78 | /* |
116 | * Only encode if there is enough space given. In practice | 79 | * Only encode if there is enough space given. In practice |
@@ -118,39 +81,118 @@ xfs_fs_encode_fh( | |||
118 | * over NFSv2 with the subtree_check export option; the other | 81 | * over NFSv2 with the subtree_check export option; the other |
119 | * seven combinations work. The real answer is "don't use v2". | 82 | * seven combinations work. The real answer is "don't use v2". |
120 | */ | 83 | */ |
121 | len = xfs_fileid_length(connectable, is64); | 84 | len = xfs_fileid_length(fileid_type); |
122 | if (*max_len < len) | 85 | if (*max_len < len) |
123 | return 255; | 86 | return 255; |
124 | *max_len = len; | 87 | *max_len = len; |
125 | 88 | ||
126 | p = xfs_fileid_encode_inode(p, inode, is64); | 89 | switch (fileid_type) { |
127 | if (connectable) { | 90 | case FILEID_INO32_GEN_PARENT: |
128 | spin_lock(&dentry->d_lock); | 91 | spin_lock(&dentry->d_lock); |
129 | p = xfs_fileid_encode_inode(p, dentry->d_parent->d_inode, is64); | 92 | fid->i32.parent_ino = dentry->d_parent->d_inode->i_ino; |
93 | fid->i32.parent_gen = dentry->d_parent->d_inode->i_generation; | ||
130 | spin_unlock(&dentry->d_lock); | 94 | spin_unlock(&dentry->d_lock); |
131 | type = 2; | 95 | /*FALLTHRU*/ |
96 | case FILEID_INO32_GEN: | ||
97 | fid->i32.ino = inode->i_ino; | ||
98 | fid->i32.gen = inode->i_generation; | ||
99 | break; | ||
100 | case FILEID_INO32_GEN_PARENT | XFS_FILEID_TYPE_64FLAG: | ||
101 | spin_lock(&dentry->d_lock); | ||
102 | fid64->parent_ino = dentry->d_parent->d_inode->i_ino; | ||
103 | fid64->parent_gen = dentry->d_parent->d_inode->i_generation; | ||
104 | spin_unlock(&dentry->d_lock); | ||
105 | /*FALLTHRU*/ | ||
106 | case FILEID_INO32_GEN | XFS_FILEID_TYPE_64FLAG: | ||
107 | fid64->ino = inode->i_ino; | ||
108 | fid64->gen = inode->i_generation; | ||
109 | break; | ||
132 | } | 110 | } |
133 | BUG_ON((p - fh) != len); | 111 | |
134 | return type | is64; | 112 | return fileid_type; |
135 | } | 113 | } |
136 | 114 | ||
137 | STATIC struct dentry * | 115 | STATIC struct inode * |
138 | xfs_fs_get_dentry( | 116 | xfs_nfs_get_inode( |
139 | struct super_block *sb, | 117 | struct super_block *sb, |
140 | void *data) | 118 | u64 ino, |
141 | { | 119 | u32 generation) |
120 | { | ||
121 | xfs_fid_t xfid; | ||
142 | bhv_vnode_t *vp; | 122 | bhv_vnode_t *vp; |
143 | struct inode *inode; | ||
144 | struct dentry *result; | ||
145 | int error; | 123 | int error; |
146 | 124 | ||
147 | error = xfs_vget(XFS_M(sb), &vp, data); | 125 | xfid.fid_len = sizeof(xfs_fid_t) - sizeof(xfid.fid_len); |
148 | if (error || vp == NULL) | 126 | xfid.fid_pad = 0; |
149 | return ERR_PTR(-ESTALE) ; | 127 | xfid.fid_ino = ino; |
128 | xfid.fid_gen = generation; | ||
150 | 129 | ||
151 | inode = vn_to_inode(vp); | 130 | error = xfs_vget(XFS_M(sb), &vp, &xfid); |
131 | if (error) | ||
132 | return ERR_PTR(-error); | ||
133 | |||
134 | return vp ? vn_to_inode(vp) : NULL; | ||
135 | } | ||
136 | |||
137 | STATIC struct dentry * | ||
138 | xfs_fs_fh_to_dentry(struct super_block *sb, struct fid *fid, | ||
139 | int fh_len, int fileid_type) | ||
140 | { | ||
141 | struct xfs_fid64 *fid64 = (struct xfs_fid64 *)fid; | ||
142 | struct inode *inode = NULL; | ||
143 | struct dentry *result; | ||
144 | |||
145 | if (fh_len < xfs_fileid_length(fileid_type)) | ||
146 | return NULL; | ||
147 | |||
148 | switch (fileid_type) { | ||
149 | case FILEID_INO32_GEN_PARENT: | ||
150 | case FILEID_INO32_GEN: | ||
151 | inode = xfs_nfs_get_inode(sb, fid->i32.ino, fid->i32.gen); | ||
152 | break; | ||
153 | case FILEID_INO32_GEN_PARENT | XFS_FILEID_TYPE_64FLAG: | ||
154 | case FILEID_INO32_GEN | XFS_FILEID_TYPE_64FLAG: | ||
155 | inode = xfs_nfs_get_inode(sb, fid64->ino, fid64->gen); | ||
156 | break; | ||
157 | } | ||
158 | |||
159 | if (!inode) | ||
160 | return NULL; | ||
161 | if (IS_ERR(inode)) | ||
162 | return ERR_PTR(PTR_ERR(inode)); | ||
163 | result = d_alloc_anon(inode); | ||
164 | if (!result) { | ||
165 | iput(inode); | ||
166 | return ERR_PTR(-ENOMEM); | ||
167 | } | ||
168 | return result; | ||
169 | } | ||
170 | |||
171 | STATIC struct dentry * | ||
172 | xfs_fs_fh_to_parent(struct super_block *sb, struct fid *fid, | ||
173 | int fh_len, int fileid_type) | ||
174 | { | ||
175 | struct xfs_fid64 *fid64 = (struct xfs_fid64 *)fid; | ||
176 | struct inode *inode = NULL; | ||
177 | struct dentry *result; | ||
178 | |||
179 | switch (fileid_type) { | ||
180 | case FILEID_INO32_GEN_PARENT: | ||
181 | inode = xfs_nfs_get_inode(sb, fid->i32.parent_ino, | ||
182 | fid->i32.parent_gen); | ||
183 | break; | ||
184 | case FILEID_INO32_GEN_PARENT | XFS_FILEID_TYPE_64FLAG: | ||
185 | inode = xfs_nfs_get_inode(sb, fid64->parent_ino, | ||
186 | fid64->parent_gen); | ||
187 | break; | ||
188 | } | ||
189 | |||
190 | if (!inode) | ||
191 | return NULL; | ||
192 | if (IS_ERR(inode)) | ||
193 | return ERR_PTR(PTR_ERR(inode)); | ||
152 | result = d_alloc_anon(inode); | 194 | result = d_alloc_anon(inode); |
153 | if (!result) { | 195 | if (!result) { |
154 | iput(inode); | 196 | iput(inode); |
155 | return ERR_PTR(-ENOMEM); | 197 | return ERR_PTR(-ENOMEM); |
156 | } | 198 | } |
@@ -178,9 +220,9 @@ xfs_fs_get_parent( | |||
178 | return parent; | 220 | return parent; |
179 | } | 221 | } |
180 | 222 | ||
181 | struct export_operations xfs_export_operations = { | 223 | const struct export_operations xfs_export_operations = { |
182 | .decode_fh = xfs_fs_decode_fh, | ||
183 | .encode_fh = xfs_fs_encode_fh, | 224 | .encode_fh = xfs_fs_encode_fh, |
225 | .fh_to_dentry = xfs_fs_fh_to_dentry, | ||
226 | .fh_to_parent = xfs_fs_fh_to_parent, | ||
184 | .get_parent = xfs_fs_get_parent, | 227 | .get_parent = xfs_fs_get_parent, |
185 | .get_dentry = xfs_fs_get_dentry, | ||
186 | }; | 228 | }; |
diff --git a/fs/xfs/linux-2.6/xfs_export.h b/fs/xfs/linux-2.6/xfs_export.h index 2f36071a86f7..3272b6ae7a35 100644 --- a/fs/xfs/linux-2.6/xfs_export.h +++ b/fs/xfs/linux-2.6/xfs_export.h | |||
@@ -59,50 +59,14 @@ | |||
59 | * a subdirectory) or use the "fsid" export option. | 59 | * a subdirectory) or use the "fsid" export option. |
60 | */ | 60 | */ |
61 | 61 | ||
62 | struct xfs_fid64 { | ||
63 | u64 ino; | ||
64 | u32 gen; | ||
65 | u64 parent_ino; | ||
66 | u32 parent_gen; | ||
67 | } __attribute__((packed)); | ||
68 | |||
62 | /* This flag goes on the wire. Don't play with it. */ | 69 | /* This flag goes on the wire. Don't play with it. */ |
63 | #define XFS_FILEID_TYPE_64FLAG 0x80 /* NFS fileid has 64bit inodes */ | 70 | #define XFS_FILEID_TYPE_64FLAG 0x80 /* NFS fileid has 64bit inodes */ |
64 | 71 | ||
65 | /* Calculate the length in u32 units of the fileid data */ | ||
66 | static inline int | ||
67 | xfs_fileid_length(int hasparent, int is64) | ||
68 | { | ||
69 | return hasparent ? (is64 ? 6 : 4) : (is64 ? 3 : 2); | ||
70 | } | ||
71 | |||
72 | /* | ||
73 | * Decode encoded inode information (either for the inode itself | ||
74 | * or the parent) into an xfs_fid_t structure. Advances and | ||
75 | * returns the new data pointer | ||
76 | */ | ||
77 | static inline __u32 * | ||
78 | xfs_fileid_decode_fid2(__u32 *p, xfs_fid_t *fid, int is64) | ||
79 | { | ||
80 | fid->fid_len = sizeof(xfs_fid_t) - sizeof(fid->fid_len); | ||
81 | fid->fid_pad = 0; | ||
82 | fid->fid_ino = *p++; | ||
83 | #if XFS_BIG_INUMS | ||
84 | if (is64) | ||
85 | fid->fid_ino |= (((__u64)(*p++)) << 32); | ||
86 | #endif | ||
87 | fid->fid_gen = *p++; | ||
88 | return p; | ||
89 | } | ||
90 | |||
91 | /* | ||
92 | * Encode inode information (either for the inode itself or the | ||
93 | * parent) into a fileid buffer. Advances and returns the new | ||
94 | * data pointer. | ||
95 | */ | ||
96 | static inline __u32 * | ||
97 | xfs_fileid_encode_inode(__u32 *p, struct inode *inode, int is64) | ||
98 | { | ||
99 | *p++ = (__u32)inode->i_ino; | ||
100 | #if XFS_BIG_INUMS | ||
101 | if (is64) | ||
102 | *p++ = (__u32)(inode->i_ino >> 32); | ||
103 | #endif | ||
104 | *p++ = inode->i_generation; | ||
105 | return p; | ||
106 | } | ||
107 | |||
108 | #endif /* __XFS_EXPORT_H__ */ | 72 | #endif /* __XFS_EXPORT_H__ */ |
diff --git a/fs/xfs/linux-2.6/xfs_super.h b/fs/xfs/linux-2.6/xfs_super.h index c78c23310fe8..3efcf45b14ab 100644 --- a/fs/xfs/linux-2.6/xfs_super.h +++ b/fs/xfs/linux-2.6/xfs_super.h | |||
@@ -118,7 +118,7 @@ extern int xfs_blkdev_get(struct xfs_mount *, const char *, | |||
118 | extern void xfs_blkdev_put(struct block_device *); | 118 | extern void xfs_blkdev_put(struct block_device *); |
119 | extern void xfs_blkdev_issue_flush(struct xfs_buftarg *); | 119 | extern void xfs_blkdev_issue_flush(struct xfs_buftarg *); |
120 | 120 | ||
121 | extern struct export_operations xfs_export_operations; | 121 | extern const struct export_operations xfs_export_operations; |
122 | 122 | ||
123 | #define XFS_M(sb) ((struct xfs_mount *)((sb)->s_fs_info)) | 123 | #define XFS_M(sb) ((struct xfs_mount *)((sb)->s_fs_info)) |
124 | 124 | ||