diff options
author | Dave Kleikamp <shaggy@austin.ibm.com> | 2005-06-20 09:44:00 -0400 |
---|---|---|
committer | Dave Kleikamp <shaggy@austin.ibm.com> | 2005-06-20 09:44:00 -0400 |
commit | d039ba24f135147f60a13bcaa768189a5b773b6e (patch) | |
tree | 444b7596ab8312b5954d15c3135052a7c09c6fbe /fs | |
parent | 72e3148a6e987974e3e949c5668e5ca812d7c818 (diff) | |
parent | 8b22c249e7de453961e4d253b19fc2a0bdd65d53 (diff) |
Merge with /home/shaggy/git/linus-clean/
Diffstat (limited to 'fs')
-rw-r--r-- | fs/binfmt_elf.c | 2 | ||||
-rw-r--r-- | fs/binfmt_flat.c | 6 | ||||
-rw-r--r-- | fs/cifs/CHANGES | 3 | ||||
-rw-r--r-- | fs/cifs/cifsfs.h | 2 | ||||
-rw-r--r-- | fs/cifs/file.c | 2 | ||||
-rw-r--r-- | fs/cifs/inode.c | 34 | ||||
-rw-r--r-- | fs/exec.c | 16 | ||||
-rw-r--r-- | fs/jbd/checkpoint.c | 5 | ||||
-rw-r--r-- | fs/mpage.c | 5 | ||||
-rw-r--r-- | fs/namei.c | 153 | ||||
-rw-r--r-- | fs/nfs/dir.c | 49 | ||||
-rw-r--r-- | fs/nfs/file.c | 42 |
12 files changed, 201 insertions, 118 deletions
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index c374be51b041..f8f6b6b76179 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c | |||
@@ -1125,7 +1125,7 @@ static int dump_write(struct file *file, const void *addr, int nr) | |||
1125 | return file->f_op->write(file, addr, nr, &file->f_pos) == nr; | 1125 | return file->f_op->write(file, addr, nr, &file->f_pos) == nr; |
1126 | } | 1126 | } |
1127 | 1127 | ||
1128 | static int dump_seek(struct file *file, off_t off) | 1128 | static int dump_seek(struct file *file, loff_t off) |
1129 | { | 1129 | { |
1130 | if (file->f_op->llseek) { | 1130 | if (file->f_op->llseek) { |
1131 | if (file->f_op->llseek(file, off, 0) != off) | 1131 | if (file->f_op->llseek(file, off, 0) != off) |
diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c index f0cd67d9d31b..c8998dc66882 100644 --- a/fs/binfmt_flat.c +++ b/fs/binfmt_flat.c | |||
@@ -520,7 +520,7 @@ static int load_flat_file(struct linux_binprm * bprm, | |||
520 | DBG_FLT("BINFMT_FLAT: ROM mapping of file (we hope)\n"); | 520 | DBG_FLT("BINFMT_FLAT: ROM mapping of file (we hope)\n"); |
521 | 521 | ||
522 | down_write(¤t->mm->mmap_sem); | 522 | down_write(¤t->mm->mmap_sem); |
523 | textpos = do_mmap(bprm->file, 0, text_len, PROT_READ|PROT_EXEC, 0, 0); | 523 | textpos = do_mmap(bprm->file, 0, text_len, PROT_READ|PROT_EXEC, MAP_SHARED, 0); |
524 | up_write(¤t->mm->mmap_sem); | 524 | up_write(¤t->mm->mmap_sem); |
525 | if (!textpos || textpos >= (unsigned long) -4096) { | 525 | if (!textpos || textpos >= (unsigned long) -4096) { |
526 | if (!textpos) | 526 | if (!textpos) |
@@ -532,7 +532,7 @@ static int load_flat_file(struct linux_binprm * bprm, | |||
532 | down_write(¤t->mm->mmap_sem); | 532 | down_write(¤t->mm->mmap_sem); |
533 | realdatastart = do_mmap(0, 0, data_len + extra + | 533 | realdatastart = do_mmap(0, 0, data_len + extra + |
534 | MAX_SHARED_LIBS * sizeof(unsigned long), | 534 | MAX_SHARED_LIBS * sizeof(unsigned long), |
535 | PROT_READ|PROT_WRITE|PROT_EXEC, 0, 0); | 535 | PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, 0); |
536 | up_write(¤t->mm->mmap_sem); | 536 | up_write(¤t->mm->mmap_sem); |
537 | 537 | ||
538 | if (realdatastart == 0 || realdatastart >= (unsigned long)-4096) { | 538 | if (realdatastart == 0 || realdatastart >= (unsigned long)-4096) { |
@@ -574,7 +574,7 @@ static int load_flat_file(struct linux_binprm * bprm, | |||
574 | down_write(¤t->mm->mmap_sem); | 574 | down_write(¤t->mm->mmap_sem); |
575 | textpos = do_mmap(0, 0, text_len + data_len + extra + | 575 | textpos = do_mmap(0, 0, text_len + data_len + extra + |
576 | MAX_SHARED_LIBS * sizeof(unsigned long), | 576 | MAX_SHARED_LIBS * sizeof(unsigned long), |
577 | PROT_READ | PROT_EXEC | PROT_WRITE, 0, 0); | 577 | PROT_READ | PROT_EXEC | PROT_WRITE, MAP_PRIVATE, 0); |
578 | up_write(¤t->mm->mmap_sem); | 578 | up_write(¤t->mm->mmap_sem); |
579 | if (!textpos || textpos >= (unsigned long) -4096) { | 579 | if (!textpos || textpos >= (unsigned long) -4096) { |
580 | if (!textpos) | 580 | if (!textpos) |
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index 95483baab706..dab4774ee7bb 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES | |||
@@ -6,7 +6,8 @@ kills the cifsd thread (NB: killing the cifs kernel threads is not | |||
6 | recommended, unmount and rmmod cifs will kill them when they are | 6 | recommended, unmount and rmmod cifs will kill them when they are |
7 | no longer needed). Fix readdir to ASCII servers (ie older servers | 7 | no longer needed). Fix readdir to ASCII servers (ie older servers |
8 | which do not support Unicode) and also require asterik. | 8 | which do not support Unicode) and also require asterik. |
9 | 9 | Fix out of memory case in which data could be written one page | |
10 | off in the page cache. | ||
10 | 11 | ||
11 | Version 1.33 | 12 | Version 1.33 |
12 | ------------ | 13 | ------------ |
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index d00b3bfe1a52..78af5850c558 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h | |||
@@ -96,5 +96,5 @@ extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t); | |||
96 | extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); | 96 | extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); |
97 | extern int cifs_ioctl (struct inode * inode, struct file * filep, | 97 | extern int cifs_ioctl (struct inode * inode, struct file * filep, |
98 | unsigned int command, unsigned long arg); | 98 | unsigned int command, unsigned long arg); |
99 | #define CIFS_VERSION "1.34" | 99 | #define CIFS_VERSION "1.35" |
100 | #endif /* _CIFSFS_H */ | 100 | #endif /* _CIFSFS_H */ |
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index dde2d251fc3d..30ab70ce5547 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
@@ -1352,6 +1352,8 @@ static void cifs_copy_cache_pages(struct address_space *mapping, | |||
1352 | GFP_KERNEL)) { | 1352 | GFP_KERNEL)) { |
1353 | page_cache_release(page); | 1353 | page_cache_release(page); |
1354 | cFYI(1, ("Add page cache failed")); | 1354 | cFYI(1, ("Add page cache failed")); |
1355 | data += PAGE_CACHE_SIZE; | ||
1356 | bytes_read -= PAGE_CACHE_SIZE; | ||
1355 | continue; | 1357 | continue; |
1356 | } | 1358 | } |
1357 | 1359 | ||
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index b8b78cbb34c9..8d336a900255 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -82,12 +82,12 @@ int cifs_get_inode_info_unix(struct inode **pinode, | |||
82 | /* get new inode */ | 82 | /* get new inode */ |
83 | if (*pinode == NULL) { | 83 | if (*pinode == NULL) { |
84 | *pinode = new_inode(sb); | 84 | *pinode = new_inode(sb); |
85 | if(*pinode == NULL) | 85 | if (*pinode == NULL) |
86 | return -ENOMEM; | 86 | return -ENOMEM; |
87 | /* Is an i_ino of zero legal? */ | 87 | /* Is an i_ino of zero legal? */ |
88 | /* Are there sanity checks we can use to ensure that | 88 | /* Are there sanity checks we can use to ensure that |
89 | the server is really filling in that field? */ | 89 | the server is really filling in that field? */ |
90 | if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { | 90 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { |
91 | (*pinode)->i_ino = | 91 | (*pinode)->i_ino = |
92 | (unsigned long)findData.UniqueId; | 92 | (unsigned long)findData.UniqueId; |
93 | } /* note ino incremented to unique num in new_inode */ | 93 | } /* note ino incremented to unique num in new_inode */ |
@@ -134,7 +134,7 @@ int cifs_get_inode_info_unix(struct inode **pinode, | |||
134 | inode->i_gid = le64_to_cpu(findData.Gid); | 134 | inode->i_gid = le64_to_cpu(findData.Gid); |
135 | inode->i_nlink = le64_to_cpu(findData.Nlinks); | 135 | inode->i_nlink = le64_to_cpu(findData.Nlinks); |
136 | 136 | ||
137 | if(is_size_safe_to_change(cifsInfo)) { | 137 | if (is_size_safe_to_change(cifsInfo)) { |
138 | /* can not safely change the file size here if the | 138 | /* can not safely change the file size here if the |
139 | client is writing to it due to potential races */ | 139 | client is writing to it due to potential races */ |
140 | 140 | ||
@@ -162,7 +162,7 @@ int cifs_get_inode_info_unix(struct inode **pinode, | |||
162 | if (S_ISREG(inode->i_mode)) { | 162 | if (S_ISREG(inode->i_mode)) { |
163 | cFYI(1, (" File inode ")); | 163 | cFYI(1, (" File inode ")); |
164 | inode->i_op = &cifs_file_inode_ops; | 164 | inode->i_op = &cifs_file_inode_ops; |
165 | if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) | 165 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) |
166 | inode->i_fop = &cifs_file_direct_ops; | 166 | inode->i_fop = &cifs_file_direct_ops; |
167 | else | 167 | else |
168 | inode->i_fop = &cifs_file_ops; | 168 | inode->i_fop = &cifs_file_ops; |
@@ -198,17 +198,17 @@ int cifs_get_inode_info(struct inode **pinode, | |||
198 | pTcon = cifs_sb->tcon; | 198 | pTcon = cifs_sb->tcon; |
199 | cFYI(1,("Getting info on %s ", search_path)); | 199 | cFYI(1,("Getting info on %s ", search_path)); |
200 | 200 | ||
201 | if((pfindData == NULL) && (*pinode != NULL)) { | 201 | if ((pfindData == NULL) && (*pinode != NULL)) { |
202 | if(CIFS_I(*pinode)->clientCanCacheRead) { | 202 | if (CIFS_I(*pinode)->clientCanCacheRead) { |
203 | cFYI(1,("No need to revalidate cached inode sizes")); | 203 | cFYI(1,("No need to revalidate cached inode sizes")); |
204 | return rc; | 204 | return rc; |
205 | } | 205 | } |
206 | } | 206 | } |
207 | 207 | ||
208 | /* if file info not passed in then get it from server */ | 208 | /* if file info not passed in then get it from server */ |
209 | if(pfindData == NULL) { | 209 | if (pfindData == NULL) { |
210 | buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); | 210 | buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); |
211 | if(buf == NULL) | 211 | if (buf == NULL) |
212 | return -ENOMEM; | 212 | return -ENOMEM; |
213 | pfindData = (FILE_ALL_INFO *)buf; | 213 | pfindData = (FILE_ALL_INFO *)buf; |
214 | /* could do find first instead but this returns more info */ | 214 | /* could do find first instead but this returns more info */ |
@@ -268,7 +268,7 @@ int cifs_get_inode_info(struct inode **pinode, | |||
268 | IndexNumber field is not guaranteed unique? */ | 268 | IndexNumber field is not guaranteed unique? */ |
269 | 269 | ||
270 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 270 | #ifdef CONFIG_CIFS_EXPERIMENTAL |
271 | if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM){ | 271 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM){ |
272 | int rc1 = 0; | 272 | int rc1 = 0; |
273 | __u64 inode_num; | 273 | __u64 inode_num; |
274 | 274 | ||
@@ -277,7 +277,7 @@ int cifs_get_inode_info(struct inode **pinode, | |||
277 | cifs_sb->local_nls, | 277 | cifs_sb->local_nls, |
278 | cifs_sb->mnt_cifs_flags & | 278 | cifs_sb->mnt_cifs_flags & |
279 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 279 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
280 | if(rc1) { | 280 | if (rc1) { |
281 | cFYI(1,("GetSrvInodeNum rc %d", rc1)); | 281 | cFYI(1,("GetSrvInodeNum rc %d", rc1)); |
282 | /* BB EOPNOSUPP disable SERVER_INUM? */ | 282 | /* BB EOPNOSUPP disable SERVER_INUM? */ |
283 | } else /* do we need cast or hash to ino? */ | 283 | } else /* do we need cast or hash to ino? */ |
@@ -355,7 +355,7 @@ int cifs_get_inode_info(struct inode **pinode, | |||
355 | if (S_ISREG(inode->i_mode)) { | 355 | if (S_ISREG(inode->i_mode)) { |
356 | cFYI(1, (" File inode ")); | 356 | cFYI(1, (" File inode ")); |
357 | inode->i_op = &cifs_file_inode_ops; | 357 | inode->i_op = &cifs_file_inode_ops; |
358 | if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) | 358 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) |
359 | inode->i_fop = &cifs_file_direct_ops; | 359 | inode->i_fop = &cifs_file_direct_ops; |
360 | else | 360 | else |
361 | inode->i_fop = &cifs_file_ops; | 361 | inode->i_fop = &cifs_file_ops; |
@@ -422,7 +422,7 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry) | |||
422 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 422 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); |
423 | 423 | ||
424 | if (!rc) { | 424 | if (!rc) { |
425 | if(direntry->d_inode) | 425 | if (direntry->d_inode) |
426 | direntry->d_inode->i_nlink--; | 426 | direntry->d_inode->i_nlink--; |
427 | } else if (rc == -ENOENT) { | 427 | } else if (rc == -ENOENT) { |
428 | d_drop(direntry); | 428 | d_drop(direntry); |
@@ -441,7 +441,7 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry) | |||
441 | cifs_sb->mnt_cifs_flags & | 441 | cifs_sb->mnt_cifs_flags & |
442 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 442 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
443 | CIFSSMBClose(xid, pTcon, netfid); | 443 | CIFSSMBClose(xid, pTcon, netfid); |
444 | if(direntry->d_inode) | 444 | if (direntry->d_inode) |
445 | direntry->d_inode->i_nlink--; | 445 | direntry->d_inode->i_nlink--; |
446 | } | 446 | } |
447 | } else if (rc == -EACCES) { | 447 | } else if (rc == -EACCES) { |
@@ -496,7 +496,7 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry) | |||
496 | cifs_sb->mnt_cifs_flags & | 496 | cifs_sb->mnt_cifs_flags & |
497 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 497 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
498 | if (!rc) { | 498 | if (!rc) { |
499 | if(direntry->d_inode) | 499 | if (direntry->d_inode) |
500 | direntry->d_inode->i_nlink--; | 500 | direntry->d_inode->i_nlink--; |
501 | } else if (rc == -ETXTBSY) { | 501 | } else if (rc == -ETXTBSY) { |
502 | int oplock = FALSE; | 502 | int oplock = FALSE; |
@@ -517,14 +517,14 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry) | |||
517 | cifs_sb->mnt_cifs_flags & | 517 | cifs_sb->mnt_cifs_flags & |
518 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 518 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
519 | CIFSSMBClose(xid, pTcon, netfid); | 519 | CIFSSMBClose(xid, pTcon, netfid); |
520 | if(direntry->d_inode) | 520 | if (direntry->d_inode) |
521 | direntry->d_inode->i_nlink--; | 521 | direntry->d_inode->i_nlink--; |
522 | } | 522 | } |
523 | /* BB if rc = -ETXTBUSY goto the rename logic BB */ | 523 | /* BB if rc = -ETXTBUSY goto the rename logic BB */ |
524 | } | 524 | } |
525 | } | 525 | } |
526 | } | 526 | } |
527 | if(direntry->d_inode) { | 527 | if (direntry->d_inode) { |
528 | cifsInode = CIFS_I(direntry->d_inode); | 528 | cifsInode = CIFS_I(direntry->d_inode); |
529 | cifsInode->time = 0; /* will force revalidate to get info | 529 | cifsInode->time = 0; /* will force revalidate to get info |
530 | when needed */ | 530 | when needed */ |
@@ -582,7 +582,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) | |||
582 | if (direntry->d_inode) | 582 | if (direntry->d_inode) |
583 | direntry->d_inode->i_nlink = 2; | 583 | direntry->d_inode->i_nlink = 2; |
584 | if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) | 584 | if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) |
585 | if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { | 585 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { |
586 | CIFSSMBUnixSetPerms(xid, pTcon, full_path, | 586 | CIFSSMBUnixSetPerms(xid, pTcon, full_path, |
587 | mode, | 587 | mode, |
588 | (__u64)current->euid, | 588 | (__u64)current->euid, |
@@ -649,6 +649,7 @@ static inline int de_thread(struct task_struct *tsk) | |||
649 | } | 649 | } |
650 | sig->group_exit_task = NULL; | 650 | sig->group_exit_task = NULL; |
651 | sig->notify_count = 0; | 651 | sig->notify_count = 0; |
652 | sig->real_timer.data = (unsigned long)current; | ||
652 | spin_unlock_irq(lock); | 653 | spin_unlock_irq(lock); |
653 | 654 | ||
654 | /* | 655 | /* |
@@ -675,10 +676,8 @@ static inline int de_thread(struct task_struct *tsk) | |||
675 | proc_dentry2 = proc_pid_unhash(leader); | 676 | proc_dentry2 = proc_pid_unhash(leader); |
676 | write_lock_irq(&tasklist_lock); | 677 | write_lock_irq(&tasklist_lock); |
677 | 678 | ||
678 | if (leader->tgid != current->tgid) | 679 | BUG_ON(leader->tgid != current->tgid); |
679 | BUG(); | 680 | BUG_ON(current->pid == current->tgid); |
680 | if (current->pid == current->tgid) | ||
681 | BUG(); | ||
682 | /* | 681 | /* |
683 | * An exec() starts a new thread group with the | 682 | * An exec() starts a new thread group with the |
684 | * TGID of the previous thread group. Rehash the | 683 | * TGID of the previous thread group. Rehash the |
@@ -726,8 +725,7 @@ static inline int de_thread(struct task_struct *tsk) | |||
726 | proc_pid_flush(proc_dentry1); | 725 | proc_pid_flush(proc_dentry1); |
727 | proc_pid_flush(proc_dentry2); | 726 | proc_pid_flush(proc_dentry2); |
728 | 727 | ||
729 | if (exit_state != EXIT_ZOMBIE) | 728 | BUG_ON(exit_state != EXIT_ZOMBIE); |
730 | BUG(); | ||
731 | release_task(leader); | 729 | release_task(leader); |
732 | } | 730 | } |
733 | 731 | ||
@@ -772,10 +770,8 @@ no_thread_group: | |||
772 | kmem_cache_free(sighand_cachep, oldsighand); | 770 | kmem_cache_free(sighand_cachep, oldsighand); |
773 | } | 771 | } |
774 | 772 | ||
775 | if (!thread_group_empty(current)) | 773 | BUG_ON(!thread_group_empty(current)); |
776 | BUG(); | 774 | BUG_ON(!thread_group_leader(current)); |
777 | if (!thread_group_leader(current)) | ||
778 | BUG(); | ||
779 | return 0; | 775 | return 0; |
780 | } | 776 | } |
781 | 777 | ||
diff --git a/fs/jbd/checkpoint.c b/fs/jbd/checkpoint.c index 98d830401c56..5a97e346bd95 100644 --- a/fs/jbd/checkpoint.c +++ b/fs/jbd/checkpoint.c | |||
@@ -188,7 +188,6 @@ static int __cleanup_transaction(journal_t *journal, transaction_t *transaction) | |||
188 | } else { | 188 | } else { |
189 | jbd_unlock_bh_state(bh); | 189 | jbd_unlock_bh_state(bh); |
190 | } | 190 | } |
191 | jh = next_jh; | ||
192 | } while (jh != last_jh); | 191 | } while (jh != last_jh); |
193 | 192 | ||
194 | return ret; | 193 | return ret; |
@@ -339,8 +338,10 @@ int log_do_checkpoint(journal_t *journal) | |||
339 | } | 338 | } |
340 | } while (jh != last_jh && !retry); | 339 | } while (jh != last_jh && !retry); |
341 | 340 | ||
342 | if (batch_count) | 341 | if (batch_count) { |
343 | __flush_batch(journal, bhs, &batch_count); | 342 | __flush_batch(journal, bhs, &batch_count); |
343 | retry = 1; | ||
344 | } | ||
344 | 345 | ||
345 | /* | 346 | /* |
346 | * If someone cleaned up this transaction while we slept, we're | 347 | * If someone cleaned up this transaction while we slept, we're |
diff --git a/fs/mpage.c b/fs/mpage.c index b92c0e64aefa..bb9aebe93862 100644 --- a/fs/mpage.c +++ b/fs/mpage.c | |||
@@ -79,8 +79,11 @@ static int mpage_end_io_write(struct bio *bio, unsigned int bytes_done, int err) | |||
79 | if (--bvec >= bio->bi_io_vec) | 79 | if (--bvec >= bio->bi_io_vec) |
80 | prefetchw(&bvec->bv_page->flags); | 80 | prefetchw(&bvec->bv_page->flags); |
81 | 81 | ||
82 | if (!uptodate) | 82 | if (!uptodate){ |
83 | SetPageError(page); | 83 | SetPageError(page); |
84 | if (page->mapping) | ||
85 | set_bit(AS_EIO, &page->mapping->flags); | ||
86 | } | ||
84 | end_page_writeback(page); | 87 | end_page_writeback(page); |
85 | } while (bvec >= bio->bi_io_vec); | 88 | } while (bvec >= bio->bi_io_vec); |
86 | bio_put(bio); | 89 | bio_put(bio); |
diff --git a/fs/namei.c b/fs/namei.c index dd78f01b6de8..a7f7f44119b3 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -493,12 +493,21 @@ fail: | |||
493 | return PTR_ERR(link); | 493 | return PTR_ERR(link); |
494 | } | 494 | } |
495 | 495 | ||
496 | static inline int __do_follow_link(struct dentry *dentry, struct nameidata *nd) | 496 | struct path { |
497 | struct vfsmount *mnt; | ||
498 | struct dentry *dentry; | ||
499 | }; | ||
500 | |||
501 | static inline int __do_follow_link(struct path *path, struct nameidata *nd) | ||
497 | { | 502 | { |
498 | int error; | 503 | int error; |
504 | struct dentry *dentry = path->dentry; | ||
499 | 505 | ||
500 | touch_atime(nd->mnt, dentry); | 506 | touch_atime(path->mnt, dentry); |
501 | nd_set_link(nd, NULL); | 507 | nd_set_link(nd, NULL); |
508 | |||
509 | if (path->mnt == nd->mnt) | ||
510 | mntget(path->mnt); | ||
502 | error = dentry->d_inode->i_op->follow_link(dentry, nd); | 511 | error = dentry->d_inode->i_op->follow_link(dentry, nd); |
503 | if (!error) { | 512 | if (!error) { |
504 | char *s = nd_get_link(nd); | 513 | char *s = nd_get_link(nd); |
@@ -507,6 +516,8 @@ static inline int __do_follow_link(struct dentry *dentry, struct nameidata *nd) | |||
507 | if (dentry->d_inode->i_op->put_link) | 516 | if (dentry->d_inode->i_op->put_link) |
508 | dentry->d_inode->i_op->put_link(dentry, nd); | 517 | dentry->d_inode->i_op->put_link(dentry, nd); |
509 | } | 518 | } |
519 | dput(dentry); | ||
520 | mntput(path->mnt); | ||
510 | 521 | ||
511 | return error; | 522 | return error; |
512 | } | 523 | } |
@@ -518,7 +529,7 @@ static inline int __do_follow_link(struct dentry *dentry, struct nameidata *nd) | |||
518 | * Without that kind of total limit, nasty chains of consecutive | 529 | * Without that kind of total limit, nasty chains of consecutive |
519 | * symlinks can cause almost arbitrarily long lookups. | 530 | * symlinks can cause almost arbitrarily long lookups. |
520 | */ | 531 | */ |
521 | static inline int do_follow_link(struct dentry *dentry, struct nameidata *nd) | 532 | static inline int do_follow_link(struct path *path, struct nameidata *nd) |
522 | { | 533 | { |
523 | int err = -ELOOP; | 534 | int err = -ELOOP; |
524 | if (current->link_count >= MAX_NESTED_LINKS) | 535 | if (current->link_count >= MAX_NESTED_LINKS) |
@@ -527,17 +538,20 @@ static inline int do_follow_link(struct dentry *dentry, struct nameidata *nd) | |||
527 | goto loop; | 538 | goto loop; |
528 | BUG_ON(nd->depth >= MAX_NESTED_LINKS); | 539 | BUG_ON(nd->depth >= MAX_NESTED_LINKS); |
529 | cond_resched(); | 540 | cond_resched(); |
530 | err = security_inode_follow_link(dentry, nd); | 541 | err = security_inode_follow_link(path->dentry, nd); |
531 | if (err) | 542 | if (err) |
532 | goto loop; | 543 | goto loop; |
533 | current->link_count++; | 544 | current->link_count++; |
534 | current->total_link_count++; | 545 | current->total_link_count++; |
535 | nd->depth++; | 546 | nd->depth++; |
536 | err = __do_follow_link(dentry, nd); | 547 | err = __do_follow_link(path, nd); |
537 | current->link_count--; | 548 | current->link_count--; |
538 | nd->depth--; | 549 | nd->depth--; |
539 | return err; | 550 | return err; |
540 | loop: | 551 | loop: |
552 | dput(path->dentry); | ||
553 | if (path->mnt != nd->mnt) | ||
554 | mntput(path->mnt); | ||
541 | path_release(nd); | 555 | path_release(nd); |
542 | return err; | 556 | return err; |
543 | } | 557 | } |
@@ -565,87 +579,91 @@ int follow_up(struct vfsmount **mnt, struct dentry **dentry) | |||
565 | /* no need for dcache_lock, as serialization is taken care in | 579 | /* no need for dcache_lock, as serialization is taken care in |
566 | * namespace.c | 580 | * namespace.c |
567 | */ | 581 | */ |
568 | static int follow_mount(struct vfsmount **mnt, struct dentry **dentry) | 582 | static int __follow_mount(struct path *path) |
569 | { | 583 | { |
570 | int res = 0; | 584 | int res = 0; |
585 | while (d_mountpoint(path->dentry)) { | ||
586 | struct vfsmount *mounted = lookup_mnt(path->mnt, path->dentry); | ||
587 | if (!mounted) | ||
588 | break; | ||
589 | dput(path->dentry); | ||
590 | if (res) | ||
591 | mntput(path->mnt); | ||
592 | path->mnt = mounted; | ||
593 | path->dentry = dget(mounted->mnt_root); | ||
594 | res = 1; | ||
595 | } | ||
596 | return res; | ||
597 | } | ||
598 | |||
599 | static void follow_mount(struct vfsmount **mnt, struct dentry **dentry) | ||
600 | { | ||
571 | while (d_mountpoint(*dentry)) { | 601 | while (d_mountpoint(*dentry)) { |
572 | struct vfsmount *mounted = lookup_mnt(*mnt, *dentry); | 602 | struct vfsmount *mounted = lookup_mnt(*mnt, *dentry); |
573 | if (!mounted) | 603 | if (!mounted) |
574 | break; | 604 | break; |
605 | dput(*dentry); | ||
575 | mntput(*mnt); | 606 | mntput(*mnt); |
576 | *mnt = mounted; | 607 | *mnt = mounted; |
577 | dput(*dentry); | ||
578 | *dentry = dget(mounted->mnt_root); | 608 | *dentry = dget(mounted->mnt_root); |
579 | res = 1; | ||
580 | } | 609 | } |
581 | return res; | ||
582 | } | 610 | } |
583 | 611 | ||
584 | /* no need for dcache_lock, as serialization is taken care in | 612 | /* no need for dcache_lock, as serialization is taken care in |
585 | * namespace.c | 613 | * namespace.c |
586 | */ | 614 | */ |
587 | static inline int __follow_down(struct vfsmount **mnt, struct dentry **dentry) | 615 | int follow_down(struct vfsmount **mnt, struct dentry **dentry) |
588 | { | 616 | { |
589 | struct vfsmount *mounted; | 617 | struct vfsmount *mounted; |
590 | 618 | ||
591 | mounted = lookup_mnt(*mnt, *dentry); | 619 | mounted = lookup_mnt(*mnt, *dentry); |
592 | if (mounted) { | 620 | if (mounted) { |
621 | dput(*dentry); | ||
593 | mntput(*mnt); | 622 | mntput(*mnt); |
594 | *mnt = mounted; | 623 | *mnt = mounted; |
595 | dput(*dentry); | ||
596 | *dentry = dget(mounted->mnt_root); | 624 | *dentry = dget(mounted->mnt_root); |
597 | return 1; | 625 | return 1; |
598 | } | 626 | } |
599 | return 0; | 627 | return 0; |
600 | } | 628 | } |
601 | 629 | ||
602 | int follow_down(struct vfsmount **mnt, struct dentry **dentry) | 630 | static inline void follow_dotdot(struct nameidata *nd) |
603 | { | ||
604 | return __follow_down(mnt,dentry); | ||
605 | } | ||
606 | |||
607 | static inline void follow_dotdot(struct vfsmount **mnt, struct dentry **dentry) | ||
608 | { | 631 | { |
609 | while(1) { | 632 | while(1) { |
610 | struct vfsmount *parent; | 633 | struct vfsmount *parent; |
611 | struct dentry *old = *dentry; | 634 | struct dentry *old = nd->dentry; |
612 | 635 | ||
613 | read_lock(¤t->fs->lock); | 636 | read_lock(¤t->fs->lock); |
614 | if (*dentry == current->fs->root && | 637 | if (nd->dentry == current->fs->root && |
615 | *mnt == current->fs->rootmnt) { | 638 | nd->mnt == current->fs->rootmnt) { |
616 | read_unlock(¤t->fs->lock); | 639 | read_unlock(¤t->fs->lock); |
617 | break; | 640 | break; |
618 | } | 641 | } |
619 | read_unlock(¤t->fs->lock); | 642 | read_unlock(¤t->fs->lock); |
620 | spin_lock(&dcache_lock); | 643 | spin_lock(&dcache_lock); |
621 | if (*dentry != (*mnt)->mnt_root) { | 644 | if (nd->dentry != nd->mnt->mnt_root) { |
622 | *dentry = dget((*dentry)->d_parent); | 645 | nd->dentry = dget(nd->dentry->d_parent); |
623 | spin_unlock(&dcache_lock); | 646 | spin_unlock(&dcache_lock); |
624 | dput(old); | 647 | dput(old); |
625 | break; | 648 | break; |
626 | } | 649 | } |
627 | spin_unlock(&dcache_lock); | 650 | spin_unlock(&dcache_lock); |
628 | spin_lock(&vfsmount_lock); | 651 | spin_lock(&vfsmount_lock); |
629 | parent = (*mnt)->mnt_parent; | 652 | parent = nd->mnt->mnt_parent; |
630 | if (parent == *mnt) { | 653 | if (parent == nd->mnt) { |
631 | spin_unlock(&vfsmount_lock); | 654 | spin_unlock(&vfsmount_lock); |
632 | break; | 655 | break; |
633 | } | 656 | } |
634 | mntget(parent); | 657 | mntget(parent); |
635 | *dentry = dget((*mnt)->mnt_mountpoint); | 658 | nd->dentry = dget(nd->mnt->mnt_mountpoint); |
636 | spin_unlock(&vfsmount_lock); | 659 | spin_unlock(&vfsmount_lock); |
637 | dput(old); | 660 | dput(old); |
638 | mntput(*mnt); | 661 | mntput(nd->mnt); |
639 | *mnt = parent; | 662 | nd->mnt = parent; |
640 | } | 663 | } |
641 | follow_mount(mnt, dentry); | 664 | follow_mount(&nd->mnt, &nd->dentry); |
642 | } | 665 | } |
643 | 666 | ||
644 | struct path { | ||
645 | struct vfsmount *mnt; | ||
646 | struct dentry *dentry; | ||
647 | }; | ||
648 | |||
649 | /* | 667 | /* |
650 | * It's more convoluted than I'd like it to be, but... it's still fairly | 668 | * It's more convoluted than I'd like it to be, but... it's still fairly |
651 | * small and for now I'd prefer to have fast path as straight as possible. | 669 | * small and for now I'd prefer to have fast path as straight as possible. |
@@ -664,6 +682,7 @@ static int do_lookup(struct nameidata *nd, struct qstr *name, | |||
664 | done: | 682 | done: |
665 | path->mnt = mnt; | 683 | path->mnt = mnt; |
666 | path->dentry = dentry; | 684 | path->dentry = dentry; |
685 | __follow_mount(path); | ||
667 | return 0; | 686 | return 0; |
668 | 687 | ||
669 | need_lookup: | 688 | need_lookup: |
@@ -751,7 +770,7 @@ static fastcall int __link_path_walk(const char * name, struct nameidata *nd) | |||
751 | case 2: | 770 | case 2: |
752 | if (this.name[1] != '.') | 771 | if (this.name[1] != '.') |
753 | break; | 772 | break; |
754 | follow_dotdot(&nd->mnt, &nd->dentry); | 773 | follow_dotdot(nd); |
755 | inode = nd->dentry->d_inode; | 774 | inode = nd->dentry->d_inode; |
756 | /* fallthrough */ | 775 | /* fallthrough */ |
757 | case 1: | 776 | case 1: |
@@ -771,8 +790,6 @@ static fastcall int __link_path_walk(const char * name, struct nameidata *nd) | |||
771 | err = do_lookup(nd, &this, &next); | 790 | err = do_lookup(nd, &this, &next); |
772 | if (err) | 791 | if (err) |
773 | break; | 792 | break; |
774 | /* Check mountpoints.. */ | ||
775 | follow_mount(&next.mnt, &next.dentry); | ||
776 | 793 | ||
777 | err = -ENOENT; | 794 | err = -ENOENT; |
778 | inode = next.dentry->d_inode; | 795 | inode = next.dentry->d_inode; |
@@ -783,10 +800,7 @@ static fastcall int __link_path_walk(const char * name, struct nameidata *nd) | |||
783 | goto out_dput; | 800 | goto out_dput; |
784 | 801 | ||
785 | if (inode->i_op->follow_link) { | 802 | if (inode->i_op->follow_link) { |
786 | mntget(next.mnt); | 803 | err = do_follow_link(&next, nd); |
787 | err = do_follow_link(next.dentry, nd); | ||
788 | dput(next.dentry); | ||
789 | mntput(next.mnt); | ||
790 | if (err) | 804 | if (err) |
791 | goto return_err; | 805 | goto return_err; |
792 | err = -ENOENT; | 806 | err = -ENOENT; |
@@ -798,6 +812,8 @@ static fastcall int __link_path_walk(const char * name, struct nameidata *nd) | |||
798 | break; | 812 | break; |
799 | } else { | 813 | } else { |
800 | dput(nd->dentry); | 814 | dput(nd->dentry); |
815 | if (nd->mnt != next.mnt) | ||
816 | mntput(nd->mnt); | ||
801 | nd->mnt = next.mnt; | 817 | nd->mnt = next.mnt; |
802 | nd->dentry = next.dentry; | 818 | nd->dentry = next.dentry; |
803 | } | 819 | } |
@@ -819,7 +835,7 @@ last_component: | |||
819 | case 2: | 835 | case 2: |
820 | if (this.name[1] != '.') | 836 | if (this.name[1] != '.') |
821 | break; | 837 | break; |
822 | follow_dotdot(&nd->mnt, &nd->dentry); | 838 | follow_dotdot(nd); |
823 | inode = nd->dentry->d_inode; | 839 | inode = nd->dentry->d_inode; |
824 | /* fallthrough */ | 840 | /* fallthrough */ |
825 | case 1: | 841 | case 1: |
@@ -833,19 +849,17 @@ last_component: | |||
833 | err = do_lookup(nd, &this, &next); | 849 | err = do_lookup(nd, &this, &next); |
834 | if (err) | 850 | if (err) |
835 | break; | 851 | break; |
836 | follow_mount(&next.mnt, &next.dentry); | ||
837 | inode = next.dentry->d_inode; | 852 | inode = next.dentry->d_inode; |
838 | if ((lookup_flags & LOOKUP_FOLLOW) | 853 | if ((lookup_flags & LOOKUP_FOLLOW) |
839 | && inode && inode->i_op && inode->i_op->follow_link) { | 854 | && inode && inode->i_op && inode->i_op->follow_link) { |
840 | mntget(next.mnt); | 855 | err = do_follow_link(&next, nd); |
841 | err = do_follow_link(next.dentry, nd); | ||
842 | dput(next.dentry); | ||
843 | mntput(next.mnt); | ||
844 | if (err) | 856 | if (err) |
845 | goto return_err; | 857 | goto return_err; |
846 | inode = nd->dentry->d_inode; | 858 | inode = nd->dentry->d_inode; |
847 | } else { | 859 | } else { |
848 | dput(nd->dentry); | 860 | dput(nd->dentry); |
861 | if (nd->mnt != next.mnt) | ||
862 | mntput(nd->mnt); | ||
849 | nd->mnt = next.mnt; | 863 | nd->mnt = next.mnt; |
850 | nd->dentry = next.dentry; | 864 | nd->dentry = next.dentry; |
851 | } | 865 | } |
@@ -885,6 +899,8 @@ return_base: | |||
885 | return 0; | 899 | return 0; |
886 | out_dput: | 900 | out_dput: |
887 | dput(next.dentry); | 901 | dput(next.dentry); |
902 | if (nd->mnt != next.mnt) | ||
903 | mntput(next.mnt); | ||
888 | break; | 904 | break; |
889 | } | 905 | } |
890 | path_release(nd); | 906 | path_release(nd); |
@@ -1398,7 +1414,7 @@ int may_open(struct nameidata *nd, int acc_mode, int flag) | |||
1398 | int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd) | 1414 | int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd) |
1399 | { | 1415 | { |
1400 | int acc_mode, error = 0; | 1416 | int acc_mode, error = 0; |
1401 | struct dentry *dentry; | 1417 | struct path path; |
1402 | struct dentry *dir; | 1418 | struct dentry *dir; |
1403 | int count = 0; | 1419 | int count = 0; |
1404 | 1420 | ||
@@ -1442,23 +1458,24 @@ int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd) | |||
1442 | dir = nd->dentry; | 1458 | dir = nd->dentry; |
1443 | nd->flags &= ~LOOKUP_PARENT; | 1459 | nd->flags &= ~LOOKUP_PARENT; |
1444 | down(&dir->d_inode->i_sem); | 1460 | down(&dir->d_inode->i_sem); |
1445 | dentry = __lookup_hash(&nd->last, nd->dentry, nd); | 1461 | path.dentry = __lookup_hash(&nd->last, nd->dentry, nd); |
1462 | path.mnt = nd->mnt; | ||
1446 | 1463 | ||
1447 | do_last: | 1464 | do_last: |
1448 | error = PTR_ERR(dentry); | 1465 | error = PTR_ERR(path.dentry); |
1449 | if (IS_ERR(dentry)) { | 1466 | if (IS_ERR(path.dentry)) { |
1450 | up(&dir->d_inode->i_sem); | 1467 | up(&dir->d_inode->i_sem); |
1451 | goto exit; | 1468 | goto exit; |
1452 | } | 1469 | } |
1453 | 1470 | ||
1454 | /* Negative dentry, just create the file */ | 1471 | /* Negative dentry, just create the file */ |
1455 | if (!dentry->d_inode) { | 1472 | if (!path.dentry->d_inode) { |
1456 | if (!IS_POSIXACL(dir->d_inode)) | 1473 | if (!IS_POSIXACL(dir->d_inode)) |
1457 | mode &= ~current->fs->umask; | 1474 | mode &= ~current->fs->umask; |
1458 | error = vfs_create(dir->d_inode, dentry, mode, nd); | 1475 | error = vfs_create(dir->d_inode, path.dentry, mode, nd); |
1459 | up(&dir->d_inode->i_sem); | 1476 | up(&dir->d_inode->i_sem); |
1460 | dput(nd->dentry); | 1477 | dput(nd->dentry); |
1461 | nd->dentry = dentry; | 1478 | nd->dentry = path.dentry; |
1462 | if (error) | 1479 | if (error) |
1463 | goto exit; | 1480 | goto exit; |
1464 | /* Don't check for write permission, don't truncate */ | 1481 | /* Don't check for write permission, don't truncate */ |
@@ -1476,22 +1493,24 @@ do_last: | |||
1476 | if (flag & O_EXCL) | 1493 | if (flag & O_EXCL) |
1477 | goto exit_dput; | 1494 | goto exit_dput; |
1478 | 1495 | ||
1479 | if (d_mountpoint(dentry)) { | 1496 | if (__follow_mount(&path)) { |
1480 | error = -ELOOP; | 1497 | error = -ELOOP; |
1481 | if (flag & O_NOFOLLOW) | 1498 | if (flag & O_NOFOLLOW) |
1482 | goto exit_dput; | 1499 | goto exit_dput; |
1483 | while (__follow_down(&nd->mnt,&dentry) && d_mountpoint(dentry)); | ||
1484 | } | 1500 | } |
1485 | error = -ENOENT; | 1501 | error = -ENOENT; |
1486 | if (!dentry->d_inode) | 1502 | if (!path.dentry->d_inode) |
1487 | goto exit_dput; | 1503 | goto exit_dput; |
1488 | if (dentry->d_inode->i_op && dentry->d_inode->i_op->follow_link) | 1504 | if (path.dentry->d_inode->i_op && path.dentry->d_inode->i_op->follow_link) |
1489 | goto do_link; | 1505 | goto do_link; |
1490 | 1506 | ||
1491 | dput(nd->dentry); | 1507 | dput(nd->dentry); |
1492 | nd->dentry = dentry; | 1508 | nd->dentry = path.dentry; |
1509 | if (nd->mnt != path.mnt) | ||
1510 | mntput(nd->mnt); | ||
1511 | nd->mnt = path.mnt; | ||
1493 | error = -EISDIR; | 1512 | error = -EISDIR; |
1494 | if (dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode)) | 1513 | if (path.dentry->d_inode && S_ISDIR(path.dentry->d_inode->i_mode)) |
1495 | goto exit; | 1514 | goto exit; |
1496 | ok: | 1515 | ok: |
1497 | error = may_open(nd, acc_mode, flag); | 1516 | error = may_open(nd, acc_mode, flag); |
@@ -1500,7 +1519,9 @@ ok: | |||
1500 | return 0; | 1519 | return 0; |
1501 | 1520 | ||
1502 | exit_dput: | 1521 | exit_dput: |
1503 | dput(dentry); | 1522 | dput(path.dentry); |
1523 | if (nd->mnt != path.mnt) | ||
1524 | mntput(path.mnt); | ||
1504 | exit: | 1525 | exit: |
1505 | path_release(nd); | 1526 | path_release(nd); |
1506 | return error; | 1527 | return error; |
@@ -1520,18 +1541,15 @@ do_link: | |||
1520 | * are done. Procfs-like symlinks just set LAST_BIND. | 1541 | * are done. Procfs-like symlinks just set LAST_BIND. |
1521 | */ | 1542 | */ |
1522 | nd->flags |= LOOKUP_PARENT; | 1543 | nd->flags |= LOOKUP_PARENT; |
1523 | error = security_inode_follow_link(dentry, nd); | 1544 | error = security_inode_follow_link(path.dentry, nd); |
1524 | if (error) | 1545 | if (error) |
1525 | goto exit_dput; | 1546 | goto exit_dput; |
1526 | error = __do_follow_link(dentry, nd); | 1547 | error = __do_follow_link(&path, nd); |
1527 | dput(dentry); | ||
1528 | if (error) | 1548 | if (error) |
1529 | return error; | 1549 | return error; |
1530 | nd->flags &= ~LOOKUP_PARENT; | 1550 | nd->flags &= ~LOOKUP_PARENT; |
1531 | if (nd->last_type == LAST_BIND) { | 1551 | if (nd->last_type == LAST_BIND) |
1532 | dentry = nd->dentry; | ||
1533 | goto ok; | 1552 | goto ok; |
1534 | } | ||
1535 | error = -EISDIR; | 1553 | error = -EISDIR; |
1536 | if (nd->last_type != LAST_NORM) | 1554 | if (nd->last_type != LAST_NORM) |
1537 | goto exit; | 1555 | goto exit; |
@@ -1546,7 +1564,8 @@ do_link: | |||
1546 | } | 1564 | } |
1547 | dir = nd->dentry; | 1565 | dir = nd->dentry; |
1548 | down(&dir->d_inode->i_sem); | 1566 | down(&dir->d_inode->i_sem); |
1549 | dentry = __lookup_hash(&nd->last, nd->dentry, nd); | 1567 | path.dentry = __lookup_hash(&nd->last, nd->dentry, nd); |
1568 | path.mnt = nd->mnt; | ||
1550 | putname(nd->last.name); | 1569 | putname(nd->last.name); |
1551 | goto do_last; | 1570 | goto do_last; |
1552 | } | 1571 | } |
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 73f96acd5d37..ff6155f5e8d9 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
@@ -528,19 +528,39 @@ static inline void nfs_renew_times(struct dentry * dentry) | |||
528 | dentry->d_time = jiffies; | 528 | dentry->d_time = jiffies; |
529 | } | 529 | } |
530 | 530 | ||
531 | /* | ||
532 | * Return the intent data that applies to this particular path component | ||
533 | * | ||
534 | * Note that the current set of intents only apply to the very last | ||
535 | * component of the path. | ||
536 | * We check for this using LOOKUP_CONTINUE and LOOKUP_PARENT. | ||
537 | */ | ||
538 | static inline unsigned int nfs_lookup_check_intent(struct nameidata *nd, unsigned int mask) | ||
539 | { | ||
540 | if (nd->flags & (LOOKUP_CONTINUE|LOOKUP_PARENT)) | ||
541 | return 0; | ||
542 | return nd->flags & mask; | ||
543 | } | ||
544 | |||
545 | /* | ||
546 | * Inode and filehandle revalidation for lookups. | ||
547 | * | ||
548 | * We force revalidation in the cases where the VFS sets LOOKUP_REVAL, | ||
549 | * or if the intent information indicates that we're about to open this | ||
550 | * particular file and the "nocto" mount flag is not set. | ||
551 | * | ||
552 | */ | ||
531 | static inline | 553 | static inline |
532 | int nfs_lookup_verify_inode(struct inode *inode, struct nameidata *nd) | 554 | int nfs_lookup_verify_inode(struct inode *inode, struct nameidata *nd) |
533 | { | 555 | { |
534 | struct nfs_server *server = NFS_SERVER(inode); | 556 | struct nfs_server *server = NFS_SERVER(inode); |
535 | 557 | ||
536 | if (nd != NULL) { | 558 | if (nd != NULL) { |
537 | int ndflags = nd->flags; | ||
538 | /* VFS wants an on-the-wire revalidation */ | 559 | /* VFS wants an on-the-wire revalidation */ |
539 | if (ndflags & LOOKUP_REVAL) | 560 | if (nd->flags & LOOKUP_REVAL) |
540 | goto out_force; | 561 | goto out_force; |
541 | /* This is an open(2) */ | 562 | /* This is an open(2) */ |
542 | if ((ndflags & LOOKUP_OPEN) && | 563 | if (nfs_lookup_check_intent(nd, LOOKUP_OPEN) != 0 && |
543 | !(ndflags & LOOKUP_CONTINUE) && | ||
544 | !(server->flags & NFS_MOUNT_NOCTO)) | 564 | !(server->flags & NFS_MOUNT_NOCTO)) |
545 | goto out_force; | 565 | goto out_force; |
546 | } | 566 | } |
@@ -560,12 +580,8 @@ static inline | |||
560 | int nfs_neg_need_reval(struct inode *dir, struct dentry *dentry, | 580 | int nfs_neg_need_reval(struct inode *dir, struct dentry *dentry, |
561 | struct nameidata *nd) | 581 | struct nameidata *nd) |
562 | { | 582 | { |
563 | int ndflags = 0; | ||
564 | |||
565 | if (nd) | ||
566 | ndflags = nd->flags; | ||
567 | /* Don't revalidate a negative dentry if we're creating a new file */ | 583 | /* Don't revalidate a negative dentry if we're creating a new file */ |
568 | if ((ndflags & LOOKUP_CREATE) && !(ndflags & LOOKUP_CONTINUE)) | 584 | if (nd != NULL && nfs_lookup_check_intent(nd, LOOKUP_CREATE) != 0) |
569 | return 0; | 585 | return 0; |
570 | return !nfs_check_verifier(dir, dentry); | 586 | return !nfs_check_verifier(dir, dentry); |
571 | } | 587 | } |
@@ -700,12 +716,16 @@ struct dentry_operations nfs_dentry_operations = { | |||
700 | .d_iput = nfs_dentry_iput, | 716 | .d_iput = nfs_dentry_iput, |
701 | }; | 717 | }; |
702 | 718 | ||
719 | /* | ||
720 | * Use intent information to check whether or not we're going to do | ||
721 | * an O_EXCL create using this path component. | ||
722 | */ | ||
703 | static inline | 723 | static inline |
704 | int nfs_is_exclusive_create(struct inode *dir, struct nameidata *nd) | 724 | int nfs_is_exclusive_create(struct inode *dir, struct nameidata *nd) |
705 | { | 725 | { |
706 | if (NFS_PROTO(dir)->version == 2) | 726 | if (NFS_PROTO(dir)->version == 2) |
707 | return 0; | 727 | return 0; |
708 | if (!nd || (nd->flags & LOOKUP_CONTINUE) || !(nd->flags & LOOKUP_CREATE)) | 728 | if (nd == NULL || nfs_lookup_check_intent(nd, LOOKUP_CREATE) == 0) |
709 | return 0; | 729 | return 0; |
710 | return (nd->intent.open.flags & O_EXCL) != 0; | 730 | return (nd->intent.open.flags & O_EXCL) != 0; |
711 | } | 731 | } |
@@ -772,12 +792,13 @@ struct dentry_operations nfs4_dentry_operations = { | |||
772 | .d_iput = nfs_dentry_iput, | 792 | .d_iput = nfs_dentry_iput, |
773 | }; | 793 | }; |
774 | 794 | ||
795 | /* | ||
796 | * Use intent information to determine whether we need to substitute | ||
797 | * the NFSv4-style stateful OPEN for the LOOKUP call | ||
798 | */ | ||
775 | static int is_atomic_open(struct inode *dir, struct nameidata *nd) | 799 | static int is_atomic_open(struct inode *dir, struct nameidata *nd) |
776 | { | 800 | { |
777 | if (!nd) | 801 | if (nd == NULL || nfs_lookup_check_intent(nd, LOOKUP_OPEN) == 0) |
778 | return 0; | ||
779 | /* Check that we are indeed trying to open this file */ | ||
780 | if ((nd->flags & LOOKUP_CONTINUE) || !(nd->flags & LOOKUP_OPEN)) | ||
781 | return 0; | 802 | return 0; |
782 | /* NFS does not (yet) have a stateful open for directories */ | 803 | /* NFS does not (yet) have a stateful open for directories */ |
783 | if (nd->flags & LOOKUP_DIRECTORY) | 804 | if (nd->flags & LOOKUP_DIRECTORY) |
diff --git a/fs/nfs/file.c b/fs/nfs/file.c index f06eee6dcff5..55c907592490 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c | |||
@@ -37,6 +37,7 @@ | |||
37 | 37 | ||
38 | static int nfs_file_open(struct inode *, struct file *); | 38 | static int nfs_file_open(struct inode *, struct file *); |
39 | static int nfs_file_release(struct inode *, struct file *); | 39 | static int nfs_file_release(struct inode *, struct file *); |
40 | static loff_t nfs_file_llseek(struct file *file, loff_t offset, int origin); | ||
40 | static int nfs_file_mmap(struct file *, struct vm_area_struct *); | 41 | static int nfs_file_mmap(struct file *, struct vm_area_struct *); |
41 | static ssize_t nfs_file_sendfile(struct file *, loff_t *, size_t, read_actor_t, void *); | 42 | static ssize_t nfs_file_sendfile(struct file *, loff_t *, size_t, read_actor_t, void *); |
42 | static ssize_t nfs_file_read(struct kiocb *, char __user *, size_t, loff_t); | 43 | static ssize_t nfs_file_read(struct kiocb *, char __user *, size_t, loff_t); |
@@ -48,7 +49,7 @@ static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl); | |||
48 | static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl); | 49 | static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl); |
49 | 50 | ||
50 | struct file_operations nfs_file_operations = { | 51 | struct file_operations nfs_file_operations = { |
51 | .llseek = remote_llseek, | 52 | .llseek = nfs_file_llseek, |
52 | .read = do_sync_read, | 53 | .read = do_sync_read, |
53 | .write = do_sync_write, | 54 | .write = do_sync_write, |
54 | .aio_read = nfs_file_read, | 55 | .aio_read = nfs_file_read, |
@@ -114,6 +115,45 @@ nfs_file_release(struct inode *inode, struct file *filp) | |||
114 | return NFS_PROTO(inode)->file_release(inode, filp); | 115 | return NFS_PROTO(inode)->file_release(inode, filp); |
115 | } | 116 | } |
116 | 117 | ||
118 | /** | ||
119 | * nfs_revalidate_size - Revalidate the file size | ||
120 | * @inode - pointer to inode struct | ||
121 | * @file - pointer to struct file | ||
122 | * | ||
123 | * Revalidates the file length. This is basically a wrapper around | ||
124 | * nfs_revalidate_inode() that takes into account the fact that we may | ||
125 | * have cached writes (in which case we don't care about the server's | ||
126 | * idea of what the file length is), or O_DIRECT (in which case we | ||
127 | * shouldn't trust the cache). | ||
128 | */ | ||
129 | static int nfs_revalidate_file_size(struct inode *inode, struct file *filp) | ||
130 | { | ||
131 | struct nfs_server *server = NFS_SERVER(inode); | ||
132 | struct nfs_inode *nfsi = NFS_I(inode); | ||
133 | |||
134 | if (server->flags & NFS_MOUNT_NOAC) | ||
135 | goto force_reval; | ||
136 | if (filp->f_flags & O_DIRECT) | ||
137 | goto force_reval; | ||
138 | if (nfsi->npages != 0) | ||
139 | return 0; | ||
140 | return nfs_revalidate_inode(server, inode); | ||
141 | force_reval: | ||
142 | return __nfs_revalidate_inode(server, inode); | ||
143 | } | ||
144 | |||
145 | static loff_t nfs_file_llseek(struct file *filp, loff_t offset, int origin) | ||
146 | { | ||
147 | /* origin == SEEK_END => we must revalidate the cached file length */ | ||
148 | if (origin == 2) { | ||
149 | struct inode *inode = filp->f_mapping->host; | ||
150 | int retval = nfs_revalidate_file_size(inode, filp); | ||
151 | if (retval < 0) | ||
152 | return (loff_t)retval; | ||
153 | } | ||
154 | return remote_llseek(filp, offset, origin); | ||
155 | } | ||
156 | |||
117 | /* | 157 | /* |
118 | * Flush all dirty pages, and check for write errors. | 158 | * Flush all dirty pages, and check for write errors. |
119 | * | 159 | * |