diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/Kconfig | 8 | ||||
-rw-r--r-- | fs/autofs4/waitq.c | 4 | ||||
-rw-r--r-- | fs/bio.c | 2 | ||||
-rw-r--r-- | fs/buffer.c | 25 | ||||
-rw-r--r-- | fs/dcookies.c | 6 | ||||
-rw-r--r-- | fs/ext3/inode.c | 2 | ||||
-rw-r--r-- | fs/hppfs/hppfs_kern.c | 7 | ||||
-rw-r--r-- | fs/inode.c | 4 | ||||
-rw-r--r-- | fs/ioprio.c | 4 | ||||
-rw-r--r-- | fs/locks.c | 4 | ||||
-rw-r--r-- | fs/namei.c | 2 | ||||
-rw-r--r-- | fs/namespace.c | 130 | ||||
-rw-r--r-- | fs/nfsd/nfs4proc.c | 6 | ||||
-rw-r--r-- | fs/nfsd/nfs4recover.c | 32 | ||||
-rw-r--r-- | fs/nfsd/nfs4state.c | 231 | ||||
-rw-r--r-- | fs/nfsd/nfs4xdr.c | 15 | ||||
-rw-r--r-- | fs/nfsd/vfs.c | 2 | ||||
-rw-r--r-- | fs/super.c | 1 |
18 files changed, 238 insertions, 247 deletions
diff --git a/fs/Kconfig b/fs/Kconfig index 062177956239..aae0686a15fb 100644 --- a/fs/Kconfig +++ b/fs/Kconfig | |||
@@ -29,6 +29,7 @@ config EXT2_FS_XATTR | |||
29 | config EXT2_FS_POSIX_ACL | 29 | config EXT2_FS_POSIX_ACL |
30 | bool "Ext2 POSIX Access Control Lists" | 30 | bool "Ext2 POSIX Access Control Lists" |
31 | depends on EXT2_FS_XATTR | 31 | depends on EXT2_FS_XATTR |
32 | select FS_POSIX_ACL | ||
32 | help | 33 | help |
33 | Posix Access Control Lists (ACLs) support permissions for users and | 34 | Posix Access Control Lists (ACLs) support permissions for users and |
34 | groups beyond the owner/group/world scheme. | 35 | groups beyond the owner/group/world scheme. |
@@ -114,6 +115,7 @@ config EXT3_FS_XATTR | |||
114 | config EXT3_FS_POSIX_ACL | 115 | config EXT3_FS_POSIX_ACL |
115 | bool "Ext3 POSIX Access Control Lists" | 116 | bool "Ext3 POSIX Access Control Lists" |
116 | depends on EXT3_FS_XATTR | 117 | depends on EXT3_FS_XATTR |
118 | select FS_POSIX_ACL | ||
117 | help | 119 | help |
118 | Posix Access Control Lists (ACLs) support permissions for users and | 120 | Posix Access Control Lists (ACLs) support permissions for users and |
119 | groups beyond the owner/group/world scheme. | 121 | groups beyond the owner/group/world scheme. |
@@ -241,6 +243,7 @@ config REISERFS_FS_XATTR | |||
241 | config REISERFS_FS_POSIX_ACL | 243 | config REISERFS_FS_POSIX_ACL |
242 | bool "ReiserFS POSIX Access Control Lists" | 244 | bool "ReiserFS POSIX Access Control Lists" |
243 | depends on REISERFS_FS_XATTR | 245 | depends on REISERFS_FS_XATTR |
246 | select FS_POSIX_ACL | ||
244 | help | 247 | help |
245 | Posix Access Control Lists (ACLs) support permissions for users and | 248 | Posix Access Control Lists (ACLs) support permissions for users and |
246 | groups beyond the owner/group/world scheme. | 249 | groups beyond the owner/group/world scheme. |
@@ -274,6 +277,7 @@ config JFS_FS | |||
274 | config JFS_POSIX_ACL | 277 | config JFS_POSIX_ACL |
275 | bool "JFS POSIX Access Control Lists" | 278 | bool "JFS POSIX Access Control Lists" |
276 | depends on JFS_FS | 279 | depends on JFS_FS |
280 | select FS_POSIX_ACL | ||
277 | help | 281 | help |
278 | Posix Access Control Lists (ACLs) support permissions for users and | 282 | Posix Access Control Lists (ACLs) support permissions for users and |
279 | groups beyond the owner/group/world scheme. | 283 | groups beyond the owner/group/world scheme. |
@@ -318,8 +322,7 @@ config FS_POSIX_ACL | |||
318 | # Never use this symbol for ifdefs. | 322 | # Never use this symbol for ifdefs. |
319 | # | 323 | # |
320 | bool | 324 | bool |
321 | depends on EXT2_FS_POSIX_ACL || EXT3_FS_POSIX_ACL || JFS_POSIX_ACL || REISERFS_FS_POSIX_ACL || NFSD_V4 | 325 | default n |
322 | default y | ||
323 | 326 | ||
324 | source "fs/xfs/Kconfig" | 327 | source "fs/xfs/Kconfig" |
325 | 328 | ||
@@ -1438,6 +1441,7 @@ config NFSD_V4 | |||
1438 | select NFSD_TCP | 1441 | select NFSD_TCP |
1439 | select CRYPTO_MD5 | 1442 | select CRYPTO_MD5 |
1440 | select CRYPTO | 1443 | select CRYPTO |
1444 | select FS_POSIX_ACL | ||
1441 | help | 1445 | help |
1442 | If you would like to include the NFSv4 server as well as the NFSv2 | 1446 | If you would like to include the NFSv4 server as well as the NFSv2 |
1443 | and NFSv3 servers, say Y here. This feature is experimental, and | 1447 | and NFSv3 servers, say Y here. This feature is experimental, and |
diff --git a/fs/autofs4/waitq.c b/fs/autofs4/waitq.c index fa2348dcd671..3df86285a1c7 100644 --- a/fs/autofs4/waitq.c +++ b/fs/autofs4/waitq.c | |||
@@ -231,8 +231,8 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry, | |||
231 | int type = (notify == NFY_MOUNT ? | 231 | int type = (notify == NFY_MOUNT ? |
232 | autofs_ptype_missing : autofs_ptype_expire_multi); | 232 | autofs_ptype_missing : autofs_ptype_expire_multi); |
233 | 233 | ||
234 | DPRINTK(("new wait id = 0x%08lx, name = %.*s, nfy=%d\n", | 234 | DPRINTK("new wait id = 0x%08lx, name = %.*s, nfy=%d\n", |
235 | (unsigned long) wq->wait_queue_token, wq->len, wq->name, notify)); | 235 | (unsigned long) wq->wait_queue_token, wq->len, wq->name, notify); |
236 | 236 | ||
237 | /* autofs4_notify_daemon() may block */ | 237 | /* autofs4_notify_daemon() may block */ |
238 | autofs4_notify_daemon(sbi, wq, type); | 238 | autofs4_notify_daemon(sbi, wq, type); |
@@ -52,7 +52,7 @@ struct biovec_slab { | |||
52 | */ | 52 | */ |
53 | 53 | ||
54 | #define BV(x) { .nr_vecs = x, .name = "biovec-"__stringify(x) } | 54 | #define BV(x) { .nr_vecs = x, .name = "biovec-"__stringify(x) } |
55 | static struct biovec_slab bvec_slabs[BIOVEC_NR_POOLS] = { | 55 | static struct biovec_slab bvec_slabs[BIOVEC_NR_POOLS] __read_mostly = { |
56 | BV(1), BV(4), BV(16), BV(64), BV(128), BV(BIO_MAX_PAGES), | 56 | BV(1), BV(4), BV(16), BV(64), BV(128), BV(BIO_MAX_PAGES), |
57 | }; | 57 | }; |
58 | #undef BV | 58 | #undef BV |
diff --git a/fs/buffer.c b/fs/buffer.c index 561e63a14966..6a25d7df89b1 100644 --- a/fs/buffer.c +++ b/fs/buffer.c | |||
@@ -513,8 +513,8 @@ static void free_more_memory(void) | |||
513 | */ | 513 | */ |
514 | static void end_buffer_async_read(struct buffer_head *bh, int uptodate) | 514 | static void end_buffer_async_read(struct buffer_head *bh, int uptodate) |
515 | { | 515 | { |
516 | static DEFINE_SPINLOCK(page_uptodate_lock); | ||
517 | unsigned long flags; | 516 | unsigned long flags; |
517 | struct buffer_head *first; | ||
518 | struct buffer_head *tmp; | 518 | struct buffer_head *tmp; |
519 | struct page *page; | 519 | struct page *page; |
520 | int page_uptodate = 1; | 520 | int page_uptodate = 1; |
@@ -536,7 +536,9 @@ static void end_buffer_async_read(struct buffer_head *bh, int uptodate) | |||
536 | * two buffer heads end IO at almost the same time and both | 536 | * two buffer heads end IO at almost the same time and both |
537 | * decide that the page is now completely done. | 537 | * decide that the page is now completely done. |
538 | */ | 538 | */ |
539 | spin_lock_irqsave(&page_uptodate_lock, flags); | 539 | first = page_buffers(page); |
540 | local_irq_save(flags); | ||
541 | bit_spin_lock(BH_Uptodate_Lock, &first->b_state); | ||
540 | clear_buffer_async_read(bh); | 542 | clear_buffer_async_read(bh); |
541 | unlock_buffer(bh); | 543 | unlock_buffer(bh); |
542 | tmp = bh; | 544 | tmp = bh; |
@@ -549,7 +551,8 @@ static void end_buffer_async_read(struct buffer_head *bh, int uptodate) | |||
549 | } | 551 | } |
550 | tmp = tmp->b_this_page; | 552 | tmp = tmp->b_this_page; |
551 | } while (tmp != bh); | 553 | } while (tmp != bh); |
552 | spin_unlock_irqrestore(&page_uptodate_lock, flags); | 554 | bit_spin_unlock(BH_Uptodate_Lock, &first->b_state); |
555 | local_irq_restore(flags); | ||
553 | 556 | ||
554 | /* | 557 | /* |
555 | * If none of the buffers had errors and they are all | 558 | * If none of the buffers had errors and they are all |
@@ -561,7 +564,8 @@ static void end_buffer_async_read(struct buffer_head *bh, int uptodate) | |||
561 | return; | 564 | return; |
562 | 565 | ||
563 | still_busy: | 566 | still_busy: |
564 | spin_unlock_irqrestore(&page_uptodate_lock, flags); | 567 | bit_spin_unlock(BH_Uptodate_Lock, &first->b_state); |
568 | local_irq_restore(flags); | ||
565 | return; | 569 | return; |
566 | } | 570 | } |
567 | 571 | ||
@@ -572,8 +576,8 @@ still_busy: | |||
572 | void end_buffer_async_write(struct buffer_head *bh, int uptodate) | 576 | void end_buffer_async_write(struct buffer_head *bh, int uptodate) |
573 | { | 577 | { |
574 | char b[BDEVNAME_SIZE]; | 578 | char b[BDEVNAME_SIZE]; |
575 | static DEFINE_SPINLOCK(page_uptodate_lock); | ||
576 | unsigned long flags; | 579 | unsigned long flags; |
580 | struct buffer_head *first; | ||
577 | struct buffer_head *tmp; | 581 | struct buffer_head *tmp; |
578 | struct page *page; | 582 | struct page *page; |
579 | 583 | ||
@@ -594,7 +598,10 @@ void end_buffer_async_write(struct buffer_head *bh, int uptodate) | |||
594 | SetPageError(page); | 598 | SetPageError(page); |
595 | } | 599 | } |
596 | 600 | ||
597 | spin_lock_irqsave(&page_uptodate_lock, flags); | 601 | first = page_buffers(page); |
602 | local_irq_save(flags); | ||
603 | bit_spin_lock(BH_Uptodate_Lock, &first->b_state); | ||
604 | |||
598 | clear_buffer_async_write(bh); | 605 | clear_buffer_async_write(bh); |
599 | unlock_buffer(bh); | 606 | unlock_buffer(bh); |
600 | tmp = bh->b_this_page; | 607 | tmp = bh->b_this_page; |
@@ -605,12 +612,14 @@ void end_buffer_async_write(struct buffer_head *bh, int uptodate) | |||
605 | } | 612 | } |
606 | tmp = tmp->b_this_page; | 613 | tmp = tmp->b_this_page; |
607 | } | 614 | } |
608 | spin_unlock_irqrestore(&page_uptodate_lock, flags); | 615 | bit_spin_unlock(BH_Uptodate_Lock, &first->b_state); |
616 | local_irq_restore(flags); | ||
609 | end_page_writeback(page); | 617 | end_page_writeback(page); |
610 | return; | 618 | return; |
611 | 619 | ||
612 | still_busy: | 620 | still_busy: |
613 | spin_unlock_irqrestore(&page_uptodate_lock, flags); | 621 | bit_spin_unlock(BH_Uptodate_Lock, &first->b_state); |
622 | local_irq_restore(flags); | ||
614 | return; | 623 | return; |
615 | } | 624 | } |
616 | 625 | ||
diff --git a/fs/dcookies.c b/fs/dcookies.c index 581aac959cd3..02aa0ddc582a 100644 --- a/fs/dcookies.c +++ b/fs/dcookies.c | |||
@@ -94,12 +94,10 @@ static struct dcookie_struct * alloc_dcookie(struct dentry * dentry, | |||
94 | if (!dcs) | 94 | if (!dcs) |
95 | return NULL; | 95 | return NULL; |
96 | 96 | ||
97 | atomic_inc(&dentry->d_count); | ||
98 | atomic_inc(&vfsmnt->mnt_count); | ||
99 | dentry->d_cookie = dcs; | 97 | dentry->d_cookie = dcs; |
100 | 98 | ||
101 | dcs->dentry = dentry; | 99 | dcs->dentry = dget(dentry); |
102 | dcs->vfsmnt = vfsmnt; | 100 | dcs->vfsmnt = mntget(vfsmnt); |
103 | hash_dcookie(dcs); | 101 | hash_dcookie(dcs); |
104 | 102 | ||
105 | return dcs; | 103 | return dcs; |
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index 0b2db4f618cb..9989fdcf4d5a 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c | |||
@@ -2663,7 +2663,7 @@ static int ext3_do_update_inode(handle_t *handle, | |||
2663 | } else for (block = 0; block < EXT3_N_BLOCKS; block++) | 2663 | } else for (block = 0; block < EXT3_N_BLOCKS; block++) |
2664 | raw_inode->i_block[block] = ei->i_data[block]; | 2664 | raw_inode->i_block[block] = ei->i_data[block]; |
2665 | 2665 | ||
2666 | if (EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE) | 2666 | if (ei->i_extra_isize) |
2667 | raw_inode->i_extra_isize = cpu_to_le16(ei->i_extra_isize); | 2667 | raw_inode->i_extra_isize = cpu_to_le16(ei->i_extra_isize); |
2668 | 2668 | ||
2669 | BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata"); | 2669 | BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata"); |
diff --git a/fs/hppfs/hppfs_kern.c b/fs/hppfs/hppfs_kern.c index f8e0cbd0cb60..6f553e17c375 100644 --- a/fs/hppfs/hppfs_kern.c +++ b/fs/hppfs/hppfs_kern.c | |||
@@ -4,6 +4,7 @@ | |||
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <linux/fs.h> | 6 | #include <linux/fs.h> |
7 | #include <linux/file.h> | ||
7 | #include <linux/module.h> | 8 | #include <linux/module.h> |
8 | #include <linux/init.h> | 9 | #include <linux/init.h> |
9 | #include <linux/slab.h> | 10 | #include <linux/slab.h> |
@@ -491,7 +492,7 @@ static int hppfs_open(struct inode *inode, struct file *file) | |||
491 | fd = open_host_sock(host_file, &filter); | 492 | fd = open_host_sock(host_file, &filter); |
492 | if(fd > 0){ | 493 | if(fd > 0){ |
493 | data->contents = hppfs_get_data(fd, filter, | 494 | data->contents = hppfs_get_data(fd, filter, |
494 | &data->proc_file, | 495 | data->proc_file, |
495 | file, &data->len); | 496 | file, &data->len); |
496 | if(!IS_ERR(data->contents)) | 497 | if(!IS_ERR(data->contents)) |
497 | data->host_fd = fd; | 498 | data->host_fd = fd; |
@@ -543,7 +544,7 @@ static int hppfs_dir_open(struct inode *inode, struct file *file) | |||
543 | static loff_t hppfs_llseek(struct file *file, loff_t off, int where) | 544 | static loff_t hppfs_llseek(struct file *file, loff_t off, int where) |
544 | { | 545 | { |
545 | struct hppfs_private *data = file->private_data; | 546 | struct hppfs_private *data = file->private_data; |
546 | struct file *proc_file = &data->proc_file; | 547 | struct file *proc_file = data->proc_file; |
547 | loff_t (*llseek)(struct file *, loff_t, int); | 548 | loff_t (*llseek)(struct file *, loff_t, int); |
548 | loff_t ret; | 549 | loff_t ret; |
549 | 550 | ||
@@ -586,7 +587,7 @@ static int hppfs_filldir(void *d, const char *name, int size, | |||
586 | static int hppfs_readdir(struct file *file, void *ent, filldir_t filldir) | 587 | static int hppfs_readdir(struct file *file, void *ent, filldir_t filldir) |
587 | { | 588 | { |
588 | struct hppfs_private *data = file->private_data; | 589 | struct hppfs_private *data = file->private_data; |
589 | struct file *proc_file = &data->proc_file; | 590 | struct file *proc_file = data->proc_file; |
590 | int (*readdir)(struct file *, void *, filldir_t); | 591 | int (*readdir)(struct file *, void *, filldir_t); |
591 | struct hppfs_dirent dirent = ((struct hppfs_dirent) | 592 | struct hppfs_dirent dirent = ((struct hppfs_dirent) |
592 | { .vfs_dirent = ent, | 593 | { .vfs_dirent = ent, |
diff --git a/fs/inode.c b/fs/inode.c index 1f9a3a2b89bc..6d695037a0a3 100644 --- a/fs/inode.c +++ b/fs/inode.c | |||
@@ -1052,7 +1052,7 @@ static void generic_forget_inode(struct inode *inode) | |||
1052 | * inode when the usage count drops to zero, and | 1052 | * inode when the usage count drops to zero, and |
1053 | * i_nlink is zero. | 1053 | * i_nlink is zero. |
1054 | */ | 1054 | */ |
1055 | static void generic_drop_inode(struct inode *inode) | 1055 | void generic_drop_inode(struct inode *inode) |
1056 | { | 1056 | { |
1057 | if (!inode->i_nlink) | 1057 | if (!inode->i_nlink) |
1058 | generic_delete_inode(inode); | 1058 | generic_delete_inode(inode); |
@@ -1060,6 +1060,8 @@ static void generic_drop_inode(struct inode *inode) | |||
1060 | generic_forget_inode(inode); | 1060 | generic_forget_inode(inode); |
1061 | } | 1061 | } |
1062 | 1062 | ||
1063 | EXPORT_SYMBOL_GPL(generic_drop_inode); | ||
1064 | |||
1063 | /* | 1065 | /* |
1064 | * Called when we're dropping the last reference | 1066 | * Called when we're dropping the last reference |
1065 | * to an inode. | 1067 | * to an inode. |
diff --git a/fs/ioprio.c b/fs/ioprio.c index 663e420636d6..97e1f088ba00 100644 --- a/fs/ioprio.c +++ b/fs/ioprio.c | |||
@@ -43,7 +43,7 @@ static int set_task_ioprio(struct task_struct *task, int ioprio) | |||
43 | return 0; | 43 | return 0; |
44 | } | 44 | } |
45 | 45 | ||
46 | asmlinkage int sys_ioprio_set(int which, int who, int ioprio) | 46 | asmlinkage long sys_ioprio_set(int which, int who, int ioprio) |
47 | { | 47 | { |
48 | int class = IOPRIO_PRIO_CLASS(ioprio); | 48 | int class = IOPRIO_PRIO_CLASS(ioprio); |
49 | int data = IOPRIO_PRIO_DATA(ioprio); | 49 | int data = IOPRIO_PRIO_DATA(ioprio); |
@@ -115,7 +115,7 @@ asmlinkage int sys_ioprio_set(int which, int who, int ioprio) | |||
115 | return ret; | 115 | return ret; |
116 | } | 116 | } |
117 | 117 | ||
118 | asmlinkage int sys_ioprio_get(int which, int who) | 118 | asmlinkage long sys_ioprio_get(int which, int who) |
119 | { | 119 | { |
120 | struct task_struct *g, *p; | 120 | struct task_struct *g, *p; |
121 | struct user_struct *user; | 121 | struct user_struct *user; |
diff --git a/fs/locks.c b/fs/locks.c index a0bc03495bd4..29fa5da6c117 100644 --- a/fs/locks.c +++ b/fs/locks.c | |||
@@ -1276,7 +1276,7 @@ int fcntl_getlease(struct file *filp) | |||
1276 | */ | 1276 | */ |
1277 | static int __setlease(struct file *filp, long arg, struct file_lock **flp) | 1277 | static int __setlease(struct file *filp, long arg, struct file_lock **flp) |
1278 | { | 1278 | { |
1279 | struct file_lock *fl, **before, **my_before = NULL, *lease = *flp; | 1279 | struct file_lock *fl, **before, **my_before = NULL, *lease; |
1280 | struct dentry *dentry = filp->f_dentry; | 1280 | struct dentry *dentry = filp->f_dentry; |
1281 | struct inode *inode = dentry->d_inode; | 1281 | struct inode *inode = dentry->d_inode; |
1282 | int error, rdlease_count = 0, wrlease_count = 0; | 1282 | int error, rdlease_count = 0, wrlease_count = 0; |
@@ -1287,6 +1287,8 @@ static int __setlease(struct file *filp, long arg, struct file_lock **flp) | |||
1287 | if (!flp || !(*flp) || !(*flp)->fl_lmops || !(*flp)->fl_lmops->fl_break) | 1287 | if (!flp || !(*flp) || !(*flp)->fl_lmops || !(*flp)->fl_lmops->fl_break) |
1288 | goto out; | 1288 | goto out; |
1289 | 1289 | ||
1290 | lease = *flp; | ||
1291 | |||
1290 | error = -EAGAIN; | 1292 | error = -EAGAIN; |
1291 | if ((arg == F_RDLCK) && (atomic_read(&inode->i_writecount) > 0)) | 1293 | if ((arg == F_RDLCK) && (atomic_read(&inode->i_writecount) > 0)) |
1292 | goto out; | 1294 | goto out; |
diff --git a/fs/namei.c b/fs/namei.c index fa8df81ce8ca..1d93cb4f7c5f 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -314,7 +314,7 @@ void path_release(struct nameidata *nd) | |||
314 | void path_release_on_umount(struct nameidata *nd) | 314 | void path_release_on_umount(struct nameidata *nd) |
315 | { | 315 | { |
316 | dput(nd->dentry); | 316 | dput(nd->dentry); |
317 | _mntput(nd->mnt); | 317 | mntput_no_expire(nd->mnt); |
318 | } | 318 | } |
319 | 319 | ||
320 | /* | 320 | /* |
diff --git a/fs/namespace.c b/fs/namespace.c index 208c079e9fdb..587eb0d707ee 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
@@ -61,7 +61,7 @@ struct vfsmount *alloc_vfsmnt(const char *name) | |||
61 | INIT_LIST_HEAD(&mnt->mnt_child); | 61 | INIT_LIST_HEAD(&mnt->mnt_child); |
62 | INIT_LIST_HEAD(&mnt->mnt_mounts); | 62 | INIT_LIST_HEAD(&mnt->mnt_mounts); |
63 | INIT_LIST_HEAD(&mnt->mnt_list); | 63 | INIT_LIST_HEAD(&mnt->mnt_list); |
64 | INIT_LIST_HEAD(&mnt->mnt_fslink); | 64 | INIT_LIST_HEAD(&mnt->mnt_expire); |
65 | if (name) { | 65 | if (name) { |
66 | int size = strlen(name)+1; | 66 | int size = strlen(name)+1; |
67 | char *newname = kmalloc(size, GFP_KERNEL); | 67 | char *newname = kmalloc(size, GFP_KERNEL); |
@@ -165,8 +165,8 @@ clone_mnt(struct vfsmount *old, struct dentry *root) | |||
165 | /* stick the duplicate mount on the same expiry list | 165 | /* stick the duplicate mount on the same expiry list |
166 | * as the original if that was on one */ | 166 | * as the original if that was on one */ |
167 | spin_lock(&vfsmount_lock); | 167 | spin_lock(&vfsmount_lock); |
168 | if (!list_empty(&old->mnt_fslink)) | 168 | if (!list_empty(&old->mnt_expire)) |
169 | list_add(&mnt->mnt_fslink, &old->mnt_fslink); | 169 | list_add(&mnt->mnt_expire, &old->mnt_expire); |
170 | spin_unlock(&vfsmount_lock); | 170 | spin_unlock(&vfsmount_lock); |
171 | } | 171 | } |
172 | return mnt; | 172 | return mnt; |
@@ -345,12 +345,13 @@ static void umount_tree(struct vfsmount *mnt) | |||
345 | for (p = mnt; p; p = next_mnt(p, mnt)) { | 345 | for (p = mnt; p; p = next_mnt(p, mnt)) { |
346 | list_del(&p->mnt_list); | 346 | list_del(&p->mnt_list); |
347 | list_add(&p->mnt_list, &kill); | 347 | list_add(&p->mnt_list, &kill); |
348 | p->mnt_namespace = NULL; | ||
348 | } | 349 | } |
349 | 350 | ||
350 | while (!list_empty(&kill)) { | 351 | while (!list_empty(&kill)) { |
351 | mnt = list_entry(kill.next, struct vfsmount, mnt_list); | 352 | mnt = list_entry(kill.next, struct vfsmount, mnt_list); |
352 | list_del_init(&mnt->mnt_list); | 353 | list_del_init(&mnt->mnt_list); |
353 | list_del_init(&mnt->mnt_fslink); | 354 | list_del_init(&mnt->mnt_expire); |
354 | if (mnt->mnt_parent == mnt) { | 355 | if (mnt->mnt_parent == mnt) { |
355 | spin_unlock(&vfsmount_lock); | 356 | spin_unlock(&vfsmount_lock); |
356 | } else { | 357 | } else { |
@@ -644,7 +645,7 @@ static int do_loopback(struct nameidata *nd, char *old_name, int recurse) | |||
644 | if (mnt) { | 645 | if (mnt) { |
645 | /* stop bind mounts from expiring */ | 646 | /* stop bind mounts from expiring */ |
646 | spin_lock(&vfsmount_lock); | 647 | spin_lock(&vfsmount_lock); |
647 | list_del_init(&mnt->mnt_fslink); | 648 | list_del_init(&mnt->mnt_expire); |
648 | spin_unlock(&vfsmount_lock); | 649 | spin_unlock(&vfsmount_lock); |
649 | 650 | ||
650 | err = graft_tree(mnt, nd); | 651 | err = graft_tree(mnt, nd); |
@@ -743,7 +744,7 @@ static int do_move_mount(struct nameidata *nd, char *old_name) | |||
743 | 744 | ||
744 | /* if the mount is moved, it should no longer be expire | 745 | /* if the mount is moved, it should no longer be expire |
745 | * automatically */ | 746 | * automatically */ |
746 | list_del_init(&old_nd.mnt->mnt_fslink); | 747 | list_del_init(&old_nd.mnt->mnt_expire); |
747 | out2: | 748 | out2: |
748 | spin_unlock(&vfsmount_lock); | 749 | spin_unlock(&vfsmount_lock); |
749 | out1: | 750 | out1: |
@@ -807,12 +808,13 @@ int do_add_mount(struct vfsmount *newmnt, struct nameidata *nd, | |||
807 | goto unlock; | 808 | goto unlock; |
808 | 809 | ||
809 | newmnt->mnt_flags = mnt_flags; | 810 | newmnt->mnt_flags = mnt_flags; |
811 | newmnt->mnt_namespace = current->namespace; | ||
810 | err = graft_tree(newmnt, nd); | 812 | err = graft_tree(newmnt, nd); |
811 | 813 | ||
812 | if (err == 0 && fslist) { | 814 | if (err == 0 && fslist) { |
813 | /* add to the specified expiration list */ | 815 | /* add to the specified expiration list */ |
814 | spin_lock(&vfsmount_lock); | 816 | spin_lock(&vfsmount_lock); |
815 | list_add_tail(&newmnt->mnt_fslink, fslist); | 817 | list_add_tail(&newmnt->mnt_expire, fslist); |
816 | spin_unlock(&vfsmount_lock); | 818 | spin_unlock(&vfsmount_lock); |
817 | } | 819 | } |
818 | 820 | ||
@@ -824,6 +826,54 @@ unlock: | |||
824 | 826 | ||
825 | EXPORT_SYMBOL_GPL(do_add_mount); | 827 | EXPORT_SYMBOL_GPL(do_add_mount); |
826 | 828 | ||
829 | static void expire_mount(struct vfsmount *mnt, struct list_head *mounts) | ||
830 | { | ||
831 | spin_lock(&vfsmount_lock); | ||
832 | |||
833 | /* | ||
834 | * Check if mount is still attached, if not, let whoever holds it deal | ||
835 | * with the sucker | ||
836 | */ | ||
837 | if (mnt->mnt_parent == mnt) { | ||
838 | spin_unlock(&vfsmount_lock); | ||
839 | return; | ||
840 | } | ||
841 | |||
842 | /* | ||
843 | * Check that it is still dead: the count should now be 2 - as | ||
844 | * contributed by the vfsmount parent and the mntget above | ||
845 | */ | ||
846 | if (atomic_read(&mnt->mnt_count) == 2) { | ||
847 | struct nameidata old_nd; | ||
848 | |||
849 | /* delete from the namespace */ | ||
850 | list_del_init(&mnt->mnt_list); | ||
851 | mnt->mnt_namespace = NULL; | ||
852 | detach_mnt(mnt, &old_nd); | ||
853 | spin_unlock(&vfsmount_lock); | ||
854 | path_release(&old_nd); | ||
855 | |||
856 | /* | ||
857 | * Now lay it to rest if this was the last ref on the superblock | ||
858 | */ | ||
859 | if (atomic_read(&mnt->mnt_sb->s_active) == 1) { | ||
860 | /* last instance - try to be smart */ | ||
861 | lock_kernel(); | ||
862 | DQUOT_OFF(mnt->mnt_sb); | ||
863 | acct_auto_close(mnt->mnt_sb); | ||
864 | unlock_kernel(); | ||
865 | } | ||
866 | mntput(mnt); | ||
867 | } else { | ||
868 | /* | ||
869 | * Someone brought it back to life whilst we didn't have any | ||
870 | * locks held so return it to the expiration list | ||
871 | */ | ||
872 | list_add_tail(&mnt->mnt_expire, mounts); | ||
873 | spin_unlock(&vfsmount_lock); | ||
874 | } | ||
875 | } | ||
876 | |||
827 | /* | 877 | /* |
828 | * process a list of expirable mountpoints with the intent of discarding any | 878 | * process a list of expirable mountpoints with the intent of discarding any |
829 | * mountpoints that aren't in use and haven't been touched since last we came | 879 | * mountpoints that aren't in use and haven't been touched since last we came |
@@ -846,13 +896,13 @@ void mark_mounts_for_expiry(struct list_head *mounts) | |||
846 | * - still marked for expiry (marked on the last call here; marks are | 896 | * - still marked for expiry (marked on the last call here; marks are |
847 | * cleared by mntput()) | 897 | * cleared by mntput()) |
848 | */ | 898 | */ |
849 | list_for_each_entry_safe(mnt, next, mounts, mnt_fslink) { | 899 | list_for_each_entry_safe(mnt, next, mounts, mnt_expire) { |
850 | if (!xchg(&mnt->mnt_expiry_mark, 1) || | 900 | if (!xchg(&mnt->mnt_expiry_mark, 1) || |
851 | atomic_read(&mnt->mnt_count) != 1) | 901 | atomic_read(&mnt->mnt_count) != 1) |
852 | continue; | 902 | continue; |
853 | 903 | ||
854 | mntget(mnt); | 904 | mntget(mnt); |
855 | list_move(&mnt->mnt_fslink, &graveyard); | 905 | list_move(&mnt->mnt_expire, &graveyard); |
856 | } | 906 | } |
857 | 907 | ||
858 | /* | 908 | /* |
@@ -862,61 +912,19 @@ void mark_mounts_for_expiry(struct list_head *mounts) | |||
862 | * - dispose of the corpse | 912 | * - dispose of the corpse |
863 | */ | 913 | */ |
864 | while (!list_empty(&graveyard)) { | 914 | while (!list_empty(&graveyard)) { |
865 | mnt = list_entry(graveyard.next, struct vfsmount, mnt_fslink); | 915 | mnt = list_entry(graveyard.next, struct vfsmount, mnt_expire); |
866 | list_del_init(&mnt->mnt_fslink); | 916 | list_del_init(&mnt->mnt_expire); |
867 | 917 | ||
868 | /* don't do anything if the namespace is dead - all the | 918 | /* don't do anything if the namespace is dead - all the |
869 | * vfsmounts from it are going away anyway */ | 919 | * vfsmounts from it are going away anyway */ |
870 | namespace = mnt->mnt_namespace; | 920 | namespace = mnt->mnt_namespace; |
871 | if (!namespace || atomic_read(&namespace->count) <= 0) | 921 | if (!namespace || !namespace->root) |
872 | continue; | 922 | continue; |
873 | get_namespace(namespace); | 923 | get_namespace(namespace); |
874 | 924 | ||
875 | spin_unlock(&vfsmount_lock); | 925 | spin_unlock(&vfsmount_lock); |
876 | down_write(&namespace->sem); | 926 | down_write(&namespace->sem); |
877 | spin_lock(&vfsmount_lock); | 927 | expire_mount(mnt, mounts); |
878 | |||
879 | /* check that it is still dead: the count should now be 2 - as | ||
880 | * contributed by the vfsmount parent and the mntget above */ | ||
881 | if (atomic_read(&mnt->mnt_count) == 2) { | ||
882 | struct vfsmount *xdmnt; | ||
883 | struct dentry *xdentry; | ||
884 | |||
885 | /* delete from the namespace */ | ||
886 | list_del_init(&mnt->mnt_list); | ||
887 | list_del_init(&mnt->mnt_child); | ||
888 | list_del_init(&mnt->mnt_hash); | ||
889 | mnt->mnt_mountpoint->d_mounted--; | ||
890 | |||
891 | xdentry = mnt->mnt_mountpoint; | ||
892 | mnt->mnt_mountpoint = mnt->mnt_root; | ||
893 | xdmnt = mnt->mnt_parent; | ||
894 | mnt->mnt_parent = mnt; | ||
895 | |||
896 | spin_unlock(&vfsmount_lock); | ||
897 | |||
898 | mntput(xdmnt); | ||
899 | dput(xdentry); | ||
900 | |||
901 | /* now lay it to rest if this was the last ref on the | ||
902 | * superblock */ | ||
903 | if (atomic_read(&mnt->mnt_sb->s_active) == 1) { | ||
904 | /* last instance - try to be smart */ | ||
905 | lock_kernel(); | ||
906 | DQUOT_OFF(mnt->mnt_sb); | ||
907 | acct_auto_close(mnt->mnt_sb); | ||
908 | unlock_kernel(); | ||
909 | } | ||
910 | |||
911 | mntput(mnt); | ||
912 | } else { | ||
913 | /* someone brought it back to life whilst we didn't | ||
914 | * have any locks held so return it to the expiration | ||
915 | * list */ | ||
916 | list_add_tail(&mnt->mnt_fslink, mounts); | ||
917 | spin_unlock(&vfsmount_lock); | ||
918 | } | ||
919 | |||
920 | up_write(&namespace->sem); | 928 | up_write(&namespace->sem); |
921 | 929 | ||
922 | mntput(mnt); | 930 | mntput(mnt); |
@@ -1449,16 +1457,12 @@ void __init mnt_init(unsigned long mempages) | |||
1449 | 1457 | ||
1450 | void __put_namespace(struct namespace *namespace) | 1458 | void __put_namespace(struct namespace *namespace) |
1451 | { | 1459 | { |
1452 | struct vfsmount *mnt; | 1460 | struct vfsmount *root = namespace->root; |
1453 | 1461 | namespace->root = NULL; | |
1462 | spin_unlock(&vfsmount_lock); | ||
1454 | down_write(&namespace->sem); | 1463 | down_write(&namespace->sem); |
1455 | spin_lock(&vfsmount_lock); | 1464 | spin_lock(&vfsmount_lock); |
1456 | 1465 | umount_tree(root); | |
1457 | list_for_each_entry(mnt, &namespace->list, mnt_list) { | ||
1458 | mnt->mnt_namespace = NULL; | ||
1459 | } | ||
1460 | |||
1461 | umount_tree(namespace->root); | ||
1462 | spin_unlock(&vfsmount_lock); | 1466 | spin_unlock(&vfsmount_lock); |
1463 | up_write(&namespace->sem); | 1467 | up_write(&namespace->sem); |
1464 | kfree(namespace); | 1468 | kfree(namespace); |
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index d71f14517b9c..e08edc17c6a0 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c | |||
@@ -169,12 +169,6 @@ nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open | |||
169 | (int)open->op_fname.len, open->op_fname.data, | 169 | (int)open->op_fname.len, open->op_fname.data, |
170 | open->op_stateowner); | 170 | open->op_stateowner); |
171 | 171 | ||
172 | if (nfs4_in_grace() && open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS) | ||
173 | return nfserr_grace; | ||
174 | |||
175 | if (!nfs4_in_grace() && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS) | ||
176 | return nfserr_no_grace; | ||
177 | |||
178 | /* This check required by spec. */ | 172 | /* This check required by spec. */ |
179 | if (open->op_create && open->op_claim_type != NFS4_OPEN_CLAIM_NULL) | 173 | if (open->op_create && open->op_claim_type != NFS4_OPEN_CLAIM_NULL) |
180 | return nfserr_inval; | 174 | return nfserr_inval; |
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c index 095f1740f3ae..57ed50fe7f85 100644 --- a/fs/nfsd/nfs4recover.c +++ b/fs/nfsd/nfs4recover.c | |||
@@ -119,25 +119,12 @@ out: | |||
119 | return status; | 119 | return status; |
120 | } | 120 | } |
121 | 121 | ||
122 | static int | 122 | static void |
123 | nfsd4_rec_fsync(struct dentry *dentry) | 123 | nfsd4_sync_rec_dir(void) |
124 | { | 124 | { |
125 | struct file *filp; | 125 | down(&rec_dir.dentry->d_inode->i_sem); |
126 | int status = nfs_ok; | 126 | nfsd_sync_dir(rec_dir.dentry); |
127 | 127 | up(&rec_dir.dentry->d_inode->i_sem); | |
128 | dprintk("NFSD: nfs4_fsync_rec_dir\n"); | ||
129 | filp = dentry_open(dget(dentry), mntget(rec_dir.mnt), O_RDWR); | ||
130 | if (IS_ERR(filp)) { | ||
131 | status = PTR_ERR(filp); | ||
132 | goto out; | ||
133 | } | ||
134 | if (filp->f_op && filp->f_op->fsync) | ||
135 | status = filp->f_op->fsync(filp, filp->f_dentry, 0); | ||
136 | fput(filp); | ||
137 | out: | ||
138 | if (status) | ||
139 | printk("nfsd4: unable to sync recovery directory\n"); | ||
140 | return status; | ||
141 | } | 128 | } |
142 | 129 | ||
143 | int | 130 | int |
@@ -176,7 +163,7 @@ out_unlock: | |||
176 | up(&rec_dir.dentry->d_inode->i_sem); | 163 | up(&rec_dir.dentry->d_inode->i_sem); |
177 | if (status == 0) { | 164 | if (status == 0) { |
178 | clp->cl_firststate = 1; | 165 | clp->cl_firststate = 1; |
179 | status = nfsd4_rec_fsync(rec_dir.dentry); | 166 | nfsd4_sync_rec_dir(); |
180 | } | 167 | } |
181 | nfs4_reset_user(uid, gid); | 168 | nfs4_reset_user(uid, gid); |
182 | dprintk("NFSD: nfsd4_create_clid_dir returns %d\n", status); | 169 | dprintk("NFSD: nfsd4_create_clid_dir returns %d\n", status); |
@@ -302,7 +289,9 @@ nfsd4_unlink_clid_dir(char *name, int namlen) | |||
302 | 289 | ||
303 | dprintk("NFSD: nfsd4_unlink_clid_dir. name %.*s\n", namlen, name); | 290 | dprintk("NFSD: nfsd4_unlink_clid_dir. name %.*s\n", namlen, name); |
304 | 291 | ||
292 | down(&rec_dir.dentry->d_inode->i_sem); | ||
305 | dentry = lookup_one_len(name, rec_dir.dentry, namlen); | 293 | dentry = lookup_one_len(name, rec_dir.dentry, namlen); |
294 | up(&rec_dir.dentry->d_inode->i_sem); | ||
306 | if (IS_ERR(dentry)) { | 295 | if (IS_ERR(dentry)) { |
307 | status = PTR_ERR(dentry); | 296 | status = PTR_ERR(dentry); |
308 | return status; | 297 | return status; |
@@ -327,11 +316,12 @@ nfsd4_remove_clid_dir(struct nfs4_client *clp) | |||
327 | if (!rec_dir_init || !clp->cl_firststate) | 316 | if (!rec_dir_init || !clp->cl_firststate) |
328 | return; | 317 | return; |
329 | 318 | ||
319 | clp->cl_firststate = 0; | ||
330 | nfs4_save_user(&uid, &gid); | 320 | nfs4_save_user(&uid, &gid); |
331 | status = nfsd4_unlink_clid_dir(clp->cl_recdir, HEXDIR_LEN-1); | 321 | status = nfsd4_unlink_clid_dir(clp->cl_recdir, HEXDIR_LEN-1); |
332 | nfs4_reset_user(uid, gid); | 322 | nfs4_reset_user(uid, gid); |
333 | if (status == 0) | 323 | if (status == 0) |
334 | status = nfsd4_rec_fsync(rec_dir.dentry); | 324 | nfsd4_sync_rec_dir(); |
335 | if (status) | 325 | if (status) |
336 | printk("NFSD: Failed to remove expired client state directory" | 326 | printk("NFSD: Failed to remove expired client state directory" |
337 | " %.*s\n", HEXDIR_LEN, clp->cl_recdir); | 327 | " %.*s\n", HEXDIR_LEN, clp->cl_recdir); |
@@ -362,7 +352,7 @@ nfsd4_recdir_purge_old(void) { | |||
362 | return; | 352 | return; |
363 | status = nfsd4_list_rec_dir(rec_dir.dentry, purge_old); | 353 | status = nfsd4_list_rec_dir(rec_dir.dentry, purge_old); |
364 | if (status == 0) | 354 | if (status == 0) |
365 | status = nfsd4_rec_fsync(rec_dir.dentry); | 355 | nfsd4_sync_rec_dir(); |
366 | if (status) | 356 | if (status) |
367 | printk("nfsd4: failed to purge old clients from recovery" | 357 | printk("nfsd4: failed to purge old clients from recovery" |
368 | " directory %s\n", rec_dir.dentry->d_name.name); | 358 | " directory %s\n", rec_dir.dentry->d_name.name); |
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 89e36526d7f2..b83f8fb441e1 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
@@ -874,6 +874,7 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, struct nfsd4_setclientid_confi | |||
874 | * change request correctly. */ | 874 | * change request correctly. */ |
875 | atomic_set(&conf->cl_callback.cb_set, 0); | 875 | atomic_set(&conf->cl_callback.cb_set, 0); |
876 | gen_confirm(conf); | 876 | gen_confirm(conf); |
877 | nfsd4_remove_clid_dir(unconf); | ||
877 | expire_client(unconf); | 878 | expire_client(unconf); |
878 | status = nfs_ok; | 879 | status = nfs_ok; |
879 | 880 | ||
@@ -1159,6 +1160,7 @@ init_stateid(struct nfs4_stateid *stp, struct nfs4_file *fp, struct nfsd4_open * | |||
1159 | stp->st_deny_bmap = 0; | 1160 | stp->st_deny_bmap = 0; |
1160 | __set_bit(open->op_share_access, &stp->st_access_bmap); | 1161 | __set_bit(open->op_share_access, &stp->st_access_bmap); |
1161 | __set_bit(open->op_share_deny, &stp->st_deny_bmap); | 1162 | __set_bit(open->op_share_deny, &stp->st_deny_bmap); |
1163 | stp->st_openstp = NULL; | ||
1162 | } | 1164 | } |
1163 | 1165 | ||
1164 | static void | 1166 | static void |
@@ -1294,7 +1296,7 @@ nfs4_share_conflict(struct svc_fh *current_fh, unsigned int deny_type) | |||
1294 | fp = find_file(ino); | 1296 | fp = find_file(ino); |
1295 | if (!fp) | 1297 | if (!fp) |
1296 | return nfs_ok; | 1298 | return nfs_ok; |
1297 | ret = nfserr_share_denied; | 1299 | ret = nfserr_locked; |
1298 | /* Search for conflicting share reservations */ | 1300 | /* Search for conflicting share reservations */ |
1299 | list_for_each_entry(stp, &fp->fi_stateids, st_perfile) { | 1301 | list_for_each_entry(stp, &fp->fi_stateids, st_perfile) { |
1300 | if (test_bit(deny_type, &stp->st_deny_bmap) || | 1302 | if (test_bit(deny_type, &stp->st_deny_bmap) || |
@@ -1482,7 +1484,7 @@ nfsd4_process_open1(struct nfsd4_open *open) | |||
1482 | if (sop) { | 1484 | if (sop) { |
1483 | open->op_stateowner = sop; | 1485 | open->op_stateowner = sop; |
1484 | /* check for replay */ | 1486 | /* check for replay */ |
1485 | if (open->op_seqid == sop->so_seqid){ | 1487 | if (open->op_seqid == sop->so_seqid - 1){ |
1486 | if (sop->so_replay.rp_buflen) | 1488 | if (sop->so_replay.rp_buflen) |
1487 | return NFSERR_REPLAY_ME; | 1489 | return NFSERR_REPLAY_ME; |
1488 | else { | 1490 | else { |
@@ -1497,7 +1499,7 @@ nfsd4_process_open1(struct nfsd4_open *open) | |||
1497 | goto renew; | 1499 | goto renew; |
1498 | } | 1500 | } |
1499 | } else if (sop->so_confirmed) { | 1501 | } else if (sop->so_confirmed) { |
1500 | if (open->op_seqid == sop->so_seqid + 1) | 1502 | if (open->op_seqid == sop->so_seqid) |
1501 | goto renew; | 1503 | goto renew; |
1502 | status = nfserr_bad_seqid; | 1504 | status = nfserr_bad_seqid; |
1503 | goto out; | 1505 | goto out; |
@@ -1530,8 +1532,6 @@ renew: | |||
1530 | status = nfs_ok; | 1532 | status = nfs_ok; |
1531 | renew_client(sop->so_client); | 1533 | renew_client(sop->so_client); |
1532 | out: | 1534 | out: |
1533 | if (status && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS) | ||
1534 | status = nfserr_reclaim_bad; | ||
1535 | return status; | 1535 | return status; |
1536 | } | 1536 | } |
1537 | 1537 | ||
@@ -1685,19 +1685,11 @@ nfs4_upgrade_open(struct svc_rqst *rqstp, struct svc_fh *cur_fh, struct nfs4_sta | |||
1685 | } | 1685 | } |
1686 | 1686 | ||
1687 | 1687 | ||
1688 | /* decrement seqid on successful reclaim, it will be bumped in encode_open */ | ||
1689 | static void | 1688 | static void |
1690 | nfs4_set_claim_prev(struct nfsd4_open *open, int *status) | 1689 | nfs4_set_claim_prev(struct nfsd4_open *open) |
1691 | { | 1690 | { |
1692 | if (open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS) { | 1691 | open->op_stateowner->so_confirmed = 1; |
1693 | if (*status) | 1692 | open->op_stateowner->so_client->cl_firststate = 1; |
1694 | *status = nfserr_reclaim_bad; | ||
1695 | else { | ||
1696 | open->op_stateowner->so_confirmed = 1; | ||
1697 | open->op_stateowner->so_client->cl_firststate = 1; | ||
1698 | open->op_stateowner->so_seqid--; | ||
1699 | } | ||
1700 | } | ||
1701 | } | 1693 | } |
1702 | 1694 | ||
1703 | /* | 1695 | /* |
@@ -1789,6 +1781,12 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf | |||
1789 | struct nfs4_delegation *dp = NULL; | 1781 | struct nfs4_delegation *dp = NULL; |
1790 | int status; | 1782 | int status; |
1791 | 1783 | ||
1784 | if (nfs4_in_grace() && open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS) | ||
1785 | return nfserr_grace; | ||
1786 | |||
1787 | if (!nfs4_in_grace() && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS) | ||
1788 | return nfserr_no_grace; | ||
1789 | |||
1792 | status = nfserr_inval; | 1790 | status = nfserr_inval; |
1793 | if (!TEST_ACCESS(open->op_share_access) || !TEST_DENY(open->op_share_deny)) | 1791 | if (!TEST_ACCESS(open->op_share_access) || !TEST_DENY(open->op_share_deny)) |
1794 | goto out; | 1792 | goto out; |
@@ -1823,6 +1821,7 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf | |||
1823 | status = nfs4_upgrade_open(rqstp, current_fh, stp, open); | 1821 | status = nfs4_upgrade_open(rqstp, current_fh, stp, open); |
1824 | if (status) | 1822 | if (status) |
1825 | goto out; | 1823 | goto out; |
1824 | update_stateid(&stp->st_stateid); | ||
1826 | } else { | 1825 | } else { |
1827 | /* Stateid was not found, this is a new OPEN */ | 1826 | /* Stateid was not found, this is a new OPEN */ |
1828 | int flags = 0; | 1827 | int flags = 0; |
@@ -1856,8 +1855,8 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf | |||
1856 | out: | 1855 | out: |
1857 | if (fp) | 1856 | if (fp) |
1858 | put_nfs4_file(fp); | 1857 | put_nfs4_file(fp); |
1859 | /* CLAIM_PREVIOUS has different error returns */ | 1858 | if (status == 0 && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS) |
1860 | nfs4_set_claim_prev(open, &status); | 1859 | nfs4_set_claim_prev(open); |
1861 | /* | 1860 | /* |
1862 | * To finish the open response, we just need to set the rflags. | 1861 | * To finish the open response, we just need to set the rflags. |
1863 | */ | 1862 | */ |
@@ -1990,14 +1989,11 @@ laundromat_main(void *not_used) | |||
1990 | queue_delayed_work(laundry_wq, &laundromat_work, t*HZ); | 1989 | queue_delayed_work(laundry_wq, &laundromat_work, t*HZ); |
1991 | } | 1990 | } |
1992 | 1991 | ||
1993 | /* search ownerid_hashtbl[] and close_lru for stateid owner | ||
1994 | * (stateid->si_stateownerid) | ||
1995 | */ | ||
1996 | static struct nfs4_stateowner * | 1992 | static struct nfs4_stateowner * |
1997 | find_openstateowner_id(u32 st_id, int flags) { | 1993 | search_close_lru(u32 st_id, int flags) |
1994 | { | ||
1998 | struct nfs4_stateowner *local = NULL; | 1995 | struct nfs4_stateowner *local = NULL; |
1999 | 1996 | ||
2000 | dprintk("NFSD: find_openstateowner_id %d\n", st_id); | ||
2001 | if (flags & CLOSE_STATE) { | 1997 | if (flags & CLOSE_STATE) { |
2002 | list_for_each_entry(local, &close_lru, so_close_lru) { | 1998 | list_for_each_entry(local, &close_lru, so_close_lru) { |
2003 | if (local->so_id == st_id) | 1999 | if (local->so_id == st_id) |
@@ -2163,14 +2159,19 @@ out: | |||
2163 | return status; | 2159 | return status; |
2164 | } | 2160 | } |
2165 | 2161 | ||
2162 | static inline int | ||
2163 | setlkflg (int type) | ||
2164 | { | ||
2165 | return (type == NFS4_READW_LT || type == NFS4_READ_LT) ? | ||
2166 | RD_STATE : WR_STATE; | ||
2167 | } | ||
2166 | 2168 | ||
2167 | /* | 2169 | /* |
2168 | * Checks for sequence id mutating operations. | 2170 | * Checks for sequence id mutating operations. |
2169 | */ | 2171 | */ |
2170 | static int | 2172 | static int |
2171 | nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *stateid, int flags, struct nfs4_stateowner **sopp, struct nfs4_stateid **stpp, clientid_t *lockclid) | 2173 | nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *stateid, int flags, struct nfs4_stateowner **sopp, struct nfs4_stateid **stpp, struct nfsd4_lock *lock) |
2172 | { | 2174 | { |
2173 | int status; | ||
2174 | struct nfs4_stateid *stp; | 2175 | struct nfs4_stateid *stp; |
2175 | struct nfs4_stateowner *sop; | 2176 | struct nfs4_stateowner *sop; |
2176 | 2177 | ||
@@ -2178,53 +2179,65 @@ nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *statei | |||
2178 | "stateid = (%08x/%08x/%08x/%08x)\n", seqid, | 2179 | "stateid = (%08x/%08x/%08x/%08x)\n", seqid, |
2179 | stateid->si_boot, stateid->si_stateownerid, stateid->si_fileid, | 2180 | stateid->si_boot, stateid->si_stateownerid, stateid->si_fileid, |
2180 | stateid->si_generation); | 2181 | stateid->si_generation); |
2181 | 2182 | ||
2182 | *stpp = NULL; | 2183 | *stpp = NULL; |
2183 | *sopp = NULL; | 2184 | *sopp = NULL; |
2184 | 2185 | ||
2185 | status = nfserr_bad_stateid; | ||
2186 | if (ZERO_STATEID(stateid) || ONE_STATEID(stateid)) { | 2186 | if (ZERO_STATEID(stateid) || ONE_STATEID(stateid)) { |
2187 | printk("NFSD: preprocess_seqid_op: magic stateid!\n"); | 2187 | printk("NFSD: preprocess_seqid_op: magic stateid!\n"); |
2188 | goto out; | 2188 | return nfserr_bad_stateid; |
2189 | } | 2189 | } |
2190 | 2190 | ||
2191 | status = nfserr_stale_stateid; | ||
2192 | if (STALE_STATEID(stateid)) | 2191 | if (STALE_STATEID(stateid)) |
2193 | goto out; | 2192 | return nfserr_stale_stateid; |
2194 | /* | 2193 | /* |
2195 | * We return BAD_STATEID if filehandle doesn't match stateid, | 2194 | * We return BAD_STATEID if filehandle doesn't match stateid, |
2196 | * the confirmed flag is incorrecly set, or the generation | 2195 | * the confirmed flag is incorrecly set, or the generation |
2197 | * number is incorrect. | 2196 | * number is incorrect. |
2198 | * If there is no entry in the openfile table for this id, | ||
2199 | * we can't always return BAD_STATEID; | ||
2200 | * this might be a retransmitted CLOSE which has arrived after | ||
2201 | * the openfile has been released. | ||
2202 | */ | 2197 | */ |
2203 | if (!(stp = find_stateid(stateid, flags))) | 2198 | stp = find_stateid(stateid, flags); |
2204 | goto no_nfs4_stateid; | 2199 | if (stp == NULL) { |
2205 | 2200 | /* | |
2206 | status = nfserr_bad_stateid; | 2201 | * Also, we should make sure this isn't just the result of |
2202 | * a replayed close: | ||
2203 | */ | ||
2204 | sop = search_close_lru(stateid->si_stateownerid, flags); | ||
2205 | if (sop == NULL) | ||
2206 | return nfserr_bad_stateid; | ||
2207 | *sopp = sop; | ||
2208 | goto check_replay; | ||
2209 | } | ||
2207 | 2210 | ||
2208 | /* for new lock stateowners: | 2211 | if (lock) { |
2209 | * check that the lock->v.new.open_stateid | ||
2210 | * refers to an open stateowner | ||
2211 | * | ||
2212 | * check that the lockclid (nfs4_lock->v.new.clientid) is the same | ||
2213 | * as the open_stateid->st_stateowner->so_client->clientid | ||
2214 | */ | ||
2215 | if (lockclid) { | ||
2216 | struct nfs4_stateowner *sop = stp->st_stateowner; | 2212 | struct nfs4_stateowner *sop = stp->st_stateowner; |
2213 | clientid_t *lockclid = &lock->v.new.clientid; | ||
2217 | struct nfs4_client *clp = sop->so_client; | 2214 | struct nfs4_client *clp = sop->so_client; |
2215 | int lkflg = 0; | ||
2216 | int status; | ||
2217 | |||
2218 | lkflg = setlkflg(lock->lk_type); | ||
2219 | |||
2220 | if (lock->lk_is_new) { | ||
2221 | if (!sop->so_is_open_owner) | ||
2222 | return nfserr_bad_stateid; | ||
2223 | if (!cmp_clid(&clp->cl_clientid, lockclid)) | ||
2224 | return nfserr_bad_stateid; | ||
2225 | /* stp is the open stateid */ | ||
2226 | status = nfs4_check_openmode(stp, lkflg); | ||
2227 | if (status) | ||
2228 | return status; | ||
2229 | } else { | ||
2230 | /* stp is the lock stateid */ | ||
2231 | status = nfs4_check_openmode(stp->st_openstp, lkflg); | ||
2232 | if (status) | ||
2233 | return status; | ||
2234 | } | ||
2218 | 2235 | ||
2219 | if (!sop->so_is_open_owner) | ||
2220 | goto out; | ||
2221 | if (!cmp_clid(&clp->cl_clientid, lockclid)) | ||
2222 | goto out; | ||
2223 | } | 2236 | } |
2224 | 2237 | ||
2225 | if ((flags & CHECK_FH) && nfs4_check_fh(current_fh, stp)) { | 2238 | if ((flags & CHECK_FH) && nfs4_check_fh(current_fh, stp)) { |
2226 | printk("NFSD: preprocess_seqid_op: fh-stateid mismatch!\n"); | 2239 | printk("NFSD: preprocess_seqid_op: fh-stateid mismatch!\n"); |
2227 | goto out; | 2240 | return nfserr_bad_stateid; |
2228 | } | 2241 | } |
2229 | 2242 | ||
2230 | *stpp = stp; | 2243 | *stpp = stp; |
@@ -2235,63 +2248,41 @@ nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *statei | |||
2235 | * For the moment, we ignore the possibility of | 2248 | * For the moment, we ignore the possibility of |
2236 | * generation number wraparound. | 2249 | * generation number wraparound. |
2237 | */ | 2250 | */ |
2238 | if (seqid != sop->so_seqid + 1) | 2251 | if (seqid != sop->so_seqid) |
2239 | goto check_replay; | 2252 | goto check_replay; |
2240 | 2253 | ||
2241 | if (sop->so_confirmed) { | 2254 | if (sop->so_confirmed && flags & CONFIRM) { |
2242 | if (flags & CONFIRM) { | 2255 | printk("NFSD: preprocess_seqid_op: expected" |
2243 | printk("NFSD: preprocess_seqid_op: expected unconfirmed stateowner!\n"); | 2256 | " unconfirmed stateowner!\n"); |
2244 | goto out; | 2257 | return nfserr_bad_stateid; |
2245 | } | ||
2246 | } | 2258 | } |
2247 | else { | 2259 | if (!sop->so_confirmed && !(flags & CONFIRM)) { |
2248 | if (!(flags & CONFIRM)) { | 2260 | printk("NFSD: preprocess_seqid_op: stateowner not" |
2249 | printk("NFSD: preprocess_seqid_op: stateowner not confirmed yet!\n"); | 2261 | " confirmed yet!\n"); |
2250 | goto out; | 2262 | return nfserr_bad_stateid; |
2251 | } | ||
2252 | } | 2263 | } |
2253 | if (stateid->si_generation > stp->st_stateid.si_generation) { | 2264 | if (stateid->si_generation > stp->st_stateid.si_generation) { |
2254 | printk("NFSD: preprocess_seqid_op: future stateid?!\n"); | 2265 | printk("NFSD: preprocess_seqid_op: future stateid?!\n"); |
2255 | goto out; | 2266 | return nfserr_bad_stateid; |
2256 | } | 2267 | } |
2257 | 2268 | ||
2258 | status = nfserr_old_stateid; | ||
2259 | if (stateid->si_generation < stp->st_stateid.si_generation) { | 2269 | if (stateid->si_generation < stp->st_stateid.si_generation) { |
2260 | printk("NFSD: preprocess_seqid_op: old stateid!\n"); | 2270 | printk("NFSD: preprocess_seqid_op: old stateid!\n"); |
2261 | goto out; | 2271 | return nfserr_old_stateid; |
2262 | } | 2272 | } |
2263 | /* XXX renew the client lease here */ | 2273 | renew_client(sop->so_client); |
2264 | status = nfs_ok; | 2274 | return nfs_ok; |
2265 | |||
2266 | out: | ||
2267 | return status; | ||
2268 | |||
2269 | no_nfs4_stateid: | ||
2270 | |||
2271 | /* | ||
2272 | * We determine whether this is a bad stateid or a replay, | ||
2273 | * starting by trying to look up the stateowner. | ||
2274 | * If stateowner is not found - stateid is bad. | ||
2275 | */ | ||
2276 | if (!(sop = find_openstateowner_id(stateid->si_stateownerid, flags))) { | ||
2277 | printk("NFSD: preprocess_seqid_op: no stateowner or nfs4_stateid!\n"); | ||
2278 | status = nfserr_bad_stateid; | ||
2279 | goto out; | ||
2280 | } | ||
2281 | *sopp = sop; | ||
2282 | 2275 | ||
2283 | check_replay: | 2276 | check_replay: |
2284 | if (seqid == sop->so_seqid) { | 2277 | if (seqid == sop->so_seqid - 1) { |
2285 | printk("NFSD: preprocess_seqid_op: retransmission?\n"); | 2278 | printk("NFSD: preprocess_seqid_op: retransmission?\n"); |
2286 | /* indicate replay to calling function */ | 2279 | /* indicate replay to calling function */ |
2287 | status = NFSERR_REPLAY_ME; | 2280 | return NFSERR_REPLAY_ME; |
2288 | } else { | ||
2289 | printk("NFSD: preprocess_seqid_op: bad seqid (expected %d, got %d\n", sop->so_seqid +1, seqid); | ||
2290 | |||
2291 | *sopp = NULL; | ||
2292 | status = nfserr_bad_seqid; | ||
2293 | } | 2281 | } |
2294 | goto out; | 2282 | printk("NFSD: preprocess_seqid_op: bad seqid (expected %d, got %d)\n", |
2283 | sop->so_seqid, seqid); | ||
2284 | *sopp = NULL; | ||
2285 | return nfserr_bad_seqid; | ||
2295 | } | 2286 | } |
2296 | 2287 | ||
2297 | int | 2288 | int |
@@ -2609,7 +2600,6 @@ find_lockstateowner_str(struct inode *inode, clientid_t *clid, | |||
2609 | * occured. | 2600 | * occured. |
2610 | * | 2601 | * |
2611 | * strhashval = lock_ownerstr_hashval | 2602 | * strhashval = lock_ownerstr_hashval |
2612 | * so_seqid = lock->lk_new_lock_seqid - 1: it gets bumped in encode | ||
2613 | */ | 2603 | */ |
2614 | 2604 | ||
2615 | static struct nfs4_stateowner * | 2605 | static struct nfs4_stateowner * |
@@ -2634,7 +2624,7 @@ alloc_init_lock_stateowner(unsigned int strhashval, struct nfs4_client *clp, str | |||
2634 | sop->so_is_open_owner = 0; | 2624 | sop->so_is_open_owner = 0; |
2635 | sop->so_id = current_ownerid++; | 2625 | sop->so_id = current_ownerid++; |
2636 | sop->so_client = clp; | 2626 | sop->so_client = clp; |
2637 | sop->so_seqid = lock->lk_new_lock_seqid - 1; | 2627 | sop->so_seqid = lock->lk_new_lock_seqid; |
2638 | sop->so_confirmed = 1; | 2628 | sop->so_confirmed = 1; |
2639 | rp = &sop->so_replay; | 2629 | rp = &sop->so_replay; |
2640 | rp->rp_status = NFSERR_SERVERFAULT; | 2630 | rp->rp_status = NFSERR_SERVERFAULT; |
@@ -2669,6 +2659,7 @@ alloc_init_lock_stateid(struct nfs4_stateowner *sop, struct nfs4_file *fp, struc | |||
2669 | stp->st_vfs_file = open_stp->st_vfs_file; /* FIXME refcount?? */ | 2659 | stp->st_vfs_file = open_stp->st_vfs_file; /* FIXME refcount?? */ |
2670 | stp->st_access_bmap = open_stp->st_access_bmap; | 2660 | stp->st_access_bmap = open_stp->st_access_bmap; |
2671 | stp->st_deny_bmap = open_stp->st_deny_bmap; | 2661 | stp->st_deny_bmap = open_stp->st_deny_bmap; |
2662 | stp->st_openstp = open_stp; | ||
2672 | 2663 | ||
2673 | out: | 2664 | out: |
2674 | return stp; | 2665 | return stp; |
@@ -2699,22 +2690,17 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock | |||
2699 | (long long) lock->lk_offset, | 2690 | (long long) lock->lk_offset, |
2700 | (long long) lock->lk_length); | 2691 | (long long) lock->lk_length); |
2701 | 2692 | ||
2702 | if (nfs4_in_grace() && !lock->lk_reclaim) | ||
2703 | return nfserr_grace; | ||
2704 | if (!nfs4_in_grace() && lock->lk_reclaim) | ||
2705 | return nfserr_no_grace; | ||
2706 | |||
2707 | if (check_lock_length(lock->lk_offset, lock->lk_length)) | 2693 | if (check_lock_length(lock->lk_offset, lock->lk_length)) |
2708 | return nfserr_inval; | 2694 | return nfserr_inval; |
2709 | 2695 | ||
2710 | nfs4_lock_state(); | 2696 | nfs4_lock_state(); |
2711 | 2697 | ||
2712 | if (lock->lk_is_new) { | 2698 | if (lock->lk_is_new) { |
2713 | /* | 2699 | /* |
2714 | * Client indicates that this is a new lockowner. | 2700 | * Client indicates that this is a new lockowner. |
2715 | * Use open owner and open stateid to create lock owner and lock | 2701 | * Use open owner and open stateid to create lock owner and |
2716 | * stateid. | 2702 | * lock stateid. |
2717 | */ | 2703 | */ |
2718 | struct nfs4_stateid *open_stp = NULL; | 2704 | struct nfs4_stateid *open_stp = NULL; |
2719 | struct nfs4_file *fp; | 2705 | struct nfs4_file *fp; |
2720 | 2706 | ||
@@ -2724,23 +2710,14 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock | |||
2724 | goto out; | 2710 | goto out; |
2725 | } | 2711 | } |
2726 | 2712 | ||
2727 | /* is the new lock seqid presented by the client zero? */ | ||
2728 | status = nfserr_bad_seqid; | ||
2729 | if (lock->v.new.lock_seqid != 0) | ||
2730 | goto out; | ||
2731 | |||
2732 | /* validate and update open stateid and open seqid */ | 2713 | /* validate and update open stateid and open seqid */ |
2733 | status = nfs4_preprocess_seqid_op(current_fh, | 2714 | status = nfs4_preprocess_seqid_op(current_fh, |
2734 | lock->lk_new_open_seqid, | 2715 | lock->lk_new_open_seqid, |
2735 | &lock->lk_new_open_stateid, | 2716 | &lock->lk_new_open_stateid, |
2736 | CHECK_FH | OPEN_STATE, | 2717 | CHECK_FH | OPEN_STATE, |
2737 | &open_sop, &open_stp, | 2718 | &open_sop, &open_stp, lock); |
2738 | &lock->v.new.clientid); | 2719 | if (status) |
2739 | if (status) { | ||
2740 | if (lock->lk_reclaim) | ||
2741 | status = nfserr_reclaim_bad; | ||
2742 | goto out; | 2720 | goto out; |
2743 | } | ||
2744 | /* create lockowner and lock stateid */ | 2721 | /* create lockowner and lock stateid */ |
2745 | fp = open_stp->st_file; | 2722 | fp = open_stp->st_file; |
2746 | strhashval = lock_ownerstr_hashval(fp->fi_inode, | 2723 | strhashval = lock_ownerstr_hashval(fp->fi_inode, |
@@ -2766,7 +2743,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock | |||
2766 | lock->lk_old_lock_seqid, | 2743 | lock->lk_old_lock_seqid, |
2767 | &lock->lk_old_lock_stateid, | 2744 | &lock->lk_old_lock_stateid, |
2768 | CHECK_FH | LOCK_STATE, | 2745 | CHECK_FH | LOCK_STATE, |
2769 | &lock->lk_stateowner, &lock_stp, NULL); | 2746 | &lock->lk_stateowner, &lock_stp, lock); |
2770 | if (status) | 2747 | if (status) |
2771 | goto out; | 2748 | goto out; |
2772 | } | 2749 | } |
@@ -2778,6 +2755,13 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock | |||
2778 | goto out; | 2755 | goto out; |
2779 | } | 2756 | } |
2780 | 2757 | ||
2758 | status = nfserr_grace; | ||
2759 | if (nfs4_in_grace() && !lock->lk_reclaim) | ||
2760 | goto out; | ||
2761 | status = nfserr_no_grace; | ||
2762 | if (!nfs4_in_grace() && lock->lk_reclaim) | ||
2763 | goto out; | ||
2764 | |||
2781 | locks_init_lock(&file_lock); | 2765 | locks_init_lock(&file_lock); |
2782 | switch (lock->lk_type) { | 2766 | switch (lock->lk_type) { |
2783 | case NFS4_READ_LT: | 2767 | case NFS4_READ_LT: |
@@ -2844,10 +2828,10 @@ conflicting_lock: | |||
2844 | out_destroy_new_stateid: | 2828 | out_destroy_new_stateid: |
2845 | if (lock->lk_is_new) { | 2829 | if (lock->lk_is_new) { |
2846 | dprintk("NFSD: nfsd4_lock: destroy new stateid!\n"); | 2830 | dprintk("NFSD: nfsd4_lock: destroy new stateid!\n"); |
2847 | /* | 2831 | /* |
2848 | * An error encountered after instantiation of the new | 2832 | * An error encountered after instantiation of the new |
2849 | * stateid has forced us to destroy it. | 2833 | * stateid has forced us to destroy it. |
2850 | */ | 2834 | */ |
2851 | if (!seqid_mutating_err(status)) | 2835 | if (!seqid_mutating_err(status)) |
2852 | open_sop->so_seqid--; | 2836 | open_sop->so_seqid--; |
2853 | 2837 | ||
@@ -3083,7 +3067,12 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp, struct nfsd4_release_lockowner * | |||
3083 | * of the lockowner state released; so don't release any until all | 3067 | * of the lockowner state released; so don't release any until all |
3084 | * have been checked. */ | 3068 | * have been checked. */ |
3085 | status = nfs_ok; | 3069 | status = nfs_ok; |
3086 | list_for_each_entry(sop, &matches, so_perclient) { | 3070 | while (!list_empty(&matches)) { |
3071 | sop = list_entry(matches.next, struct nfs4_stateowner, | ||
3072 | so_perclient); | ||
3073 | /* unhash_stateowner deletes so_perclient only | ||
3074 | * for openowners. */ | ||
3075 | list_del(&sop->so_perclient); | ||
3087 | release_stateowner(sop); | 3076 | release_stateowner(sop); |
3088 | } | 3077 | } |
3089 | out: | 3078 | out: |
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 91fb171d2ace..4c4146350236 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c | |||
@@ -1210,16 +1210,15 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp) | |||
1210 | save = resp->p; | 1210 | save = resp->p; |
1211 | 1211 | ||
1212 | /* | 1212 | /* |
1213 | * Routine for encoding the result of a | 1213 | * Routine for encoding the result of a "seqid-mutating" NFSv4 operation. This |
1214 | * "seqid-mutating" NFSv4 operation. This is | 1214 | * is where sequence id's are incremented, and the replay cache is filled. |
1215 | * where seqids are incremented, and the | 1215 | * Note that we increment sequence id's here, at the last moment, so we're sure |
1216 | * replay cache is filled. | 1216 | * we know whether the error to be returned is a sequence id mutating error. |
1217 | */ | 1217 | */ |
1218 | 1218 | ||
1219 | #define ENCODE_SEQID_OP_TAIL(stateowner) do { \ | 1219 | #define ENCODE_SEQID_OP_TAIL(stateowner) do { \ |
1220 | if (seqid_mutating_err(nfserr) && stateowner) { \ | 1220 | if (seqid_mutating_err(nfserr) && stateowner) { \ |
1221 | if (stateowner->so_confirmed) \ | 1221 | stateowner->so_seqid++; \ |
1222 | stateowner->so_seqid++; \ | ||
1223 | stateowner->so_replay.rp_status = nfserr; \ | 1222 | stateowner->so_replay.rp_status = nfserr; \ |
1224 | stateowner->so_replay.rp_buflen = \ | 1223 | stateowner->so_replay.rp_buflen = \ |
1225 | (((char *)(resp)->p - (char *)save)); \ | 1224 | (((char *)(resp)->p - (char *)save)); \ |
@@ -1367,9 +1366,9 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp, | |||
1367 | if ((buflen -= 4) < 0) | 1366 | if ((buflen -= 4) < 0) |
1368 | goto out_resource; | 1367 | goto out_resource; |
1369 | if (exp->ex_flags & NFSEXP_NOSUBTREECHECK) | 1368 | if (exp->ex_flags & NFSEXP_NOSUBTREECHECK) |
1370 | WRITE32(NFS4_FH_VOLATILE_ANY); | 1369 | WRITE32(NFS4_FH_PERSISTENT); |
1371 | else | 1370 | else |
1372 | WRITE32(NFS4_FH_VOLATILE_ANY|NFS4_FH_VOL_RENAME); | 1371 | WRITE32(NFS4_FH_PERSISTENT|NFS4_FH_VOL_RENAME); |
1373 | } | 1372 | } |
1374 | if (bmval0 & FATTR4_WORD0_CHANGE) { | 1373 | if (bmval0 & FATTR4_WORD0_CHANGE) { |
1375 | /* | 1374 | /* |
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index be24ead89d94..5e0bf3917607 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
@@ -733,7 +733,7 @@ nfsd_sync(struct file *filp) | |||
733 | up(&inode->i_sem); | 733 | up(&inode->i_sem); |
734 | } | 734 | } |
735 | 735 | ||
736 | static void | 736 | void |
737 | nfsd_sync_dir(struct dentry *dp) | 737 | nfsd_sync_dir(struct dentry *dp) |
738 | { | 738 | { |
739 | nfsd_dosync(NULL, dp, dp->d_inode->i_fop); | 739 | nfsd_dosync(NULL, dp, dp->d_inode->i_fop); |
diff --git a/fs/super.c b/fs/super.c index 25bc1ec6bc5d..6e57ee252e14 100644 --- a/fs/super.c +++ b/fs/super.c | |||
@@ -840,7 +840,6 @@ do_kern_mount(const char *fstype, int flags, const char *name, void *data) | |||
840 | mnt->mnt_root = dget(sb->s_root); | 840 | mnt->mnt_root = dget(sb->s_root); |
841 | mnt->mnt_mountpoint = sb->s_root; | 841 | mnt->mnt_mountpoint = sb->s_root; |
842 | mnt->mnt_parent = mnt; | 842 | mnt->mnt_parent = mnt; |
843 | mnt->mnt_namespace = current->namespace; | ||
844 | up_write(&sb->s_umount); | 843 | up_write(&sb->s_umount); |
845 | free_secdata(secdata); | 844 | free_secdata(secdata); |
846 | put_filesystem(type); | 845 | put_filesystem(type); |