diff options
author | David Woodhouse <dwmw2@infradead.org> | 2006-12-01 04:56:43 -0500 |
---|---|---|
committer | David Woodhouse <dwmw2@infradead.org> | 2006-12-01 04:56:43 -0500 |
commit | bd3c97a7c718bfb9f1e4f31c16c383a5c6f815eb (patch) | |
tree | 3f56594e813c6f35cbacbdb3e137ba5bfd0b3069 /fs | |
parent | 6c33cafc794d07c9254c160789120a0e98c088c9 (diff) | |
parent | 0215ffb08ce99e2bb59eca114a99499a4d06e704 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
Diffstat (limited to 'fs')
70 files changed, 1098 insertions, 631 deletions
diff --git a/fs/Kconfig b/fs/Kconfig index fee318e6f4bb..7b1511d50b05 100644 --- a/fs/Kconfig +++ b/fs/Kconfig | |||
@@ -1777,6 +1777,7 @@ config RPCSEC_GSS_KRB5 | |||
1777 | select CRYPTO | 1777 | select CRYPTO |
1778 | select CRYPTO_MD5 | 1778 | select CRYPTO_MD5 |
1779 | select CRYPTO_DES | 1779 | select CRYPTO_DES |
1780 | select CRYPTO_CBC | ||
1780 | help | 1781 | help |
1781 | Provides for secure RPC calls by means of a gss-api | 1782 | Provides for secure RPC calls by means of a gss-api |
1782 | mechanism based on Kerberos V5. This is required for | 1783 | mechanism based on Kerberos V5. This is required for |
@@ -1795,6 +1796,7 @@ config RPCSEC_GSS_SPKM3 | |||
1795 | select CRYPTO_MD5 | 1796 | select CRYPTO_MD5 |
1796 | select CRYPTO_DES | 1797 | select CRYPTO_DES |
1797 | select CRYPTO_CAST5 | 1798 | select CRYPTO_CAST5 |
1799 | select CRYPTO_CBC | ||
1798 | help | 1800 | help |
1799 | Provides for secure RPC calls by means of a gss-api | 1801 | Provides for secure RPC calls by means of a gss-api |
1800 | mechanism based on the SPKM3 public-key mechanism. | 1802 | mechanism based on the SPKM3 public-key mechanism. |
@@ -2058,8 +2060,7 @@ config CODA_FS_OLD_API | |||
2058 | For most cases you probably want to say N. | 2060 | For most cases you probably want to say N. |
2059 | 2061 | ||
2060 | config AFS_FS | 2062 | config AFS_FS |
2061 | # for fs/nls/Config.in | 2063 | tristate "Andrew File System support (AFS) (EXPERIMENTAL)" |
2062 | tristate "Andrew File System support (AFS) (Experimental)" | ||
2063 | depends on INET && EXPERIMENTAL | 2064 | depends on INET && EXPERIMENTAL |
2064 | select RXRPC | 2065 | select RXRPC |
2065 | help | 2066 | help |
diff --git a/fs/autofs/inode.c b/fs/autofs/inode.c index 54c518c89e4c..38ede5c9d6fd 100644 --- a/fs/autofs/inode.c +++ b/fs/autofs/inode.c | |||
@@ -25,6 +25,14 @@ void autofs_kill_sb(struct super_block *sb) | |||
25 | struct autofs_sb_info *sbi = autofs_sbi(sb); | 25 | struct autofs_sb_info *sbi = autofs_sbi(sb); |
26 | unsigned int n; | 26 | unsigned int n; |
27 | 27 | ||
28 | /* | ||
29 | * In the event of a failure in get_sb_nodev the superblock | ||
30 | * info is not present so nothing else has been setup, so | ||
31 | * just exit when we are called from deactivate_super. | ||
32 | */ | ||
33 | if (!sbi) | ||
34 | return; | ||
35 | |||
28 | if ( !sbi->catatonic ) | 36 | if ( !sbi->catatonic ) |
29 | autofs_catatonic_mode(sbi); /* Free wait queues, close pipe */ | 37 | autofs_catatonic_mode(sbi); /* Free wait queues, close pipe */ |
30 | 38 | ||
@@ -136,7 +144,8 @@ int autofs_fill_super(struct super_block *s, void *data, int silent) | |||
136 | 144 | ||
137 | s->s_fs_info = sbi; | 145 | s->s_fs_info = sbi; |
138 | sbi->magic = AUTOFS_SBI_MAGIC; | 146 | sbi->magic = AUTOFS_SBI_MAGIC; |
139 | sbi->catatonic = 0; | 147 | sbi->pipe = NULL; |
148 | sbi->catatonic = 1; | ||
140 | sbi->exp_timeout = 0; | 149 | sbi->exp_timeout = 0; |
141 | sbi->oz_pgrp = process_group(current); | 150 | sbi->oz_pgrp = process_group(current); |
142 | autofs_initialize_hash(&sbi->dirhash); | 151 | autofs_initialize_hash(&sbi->dirhash); |
@@ -180,6 +189,7 @@ int autofs_fill_super(struct super_block *s, void *data, int silent) | |||
180 | if ( !pipe->f_op || !pipe->f_op->write ) | 189 | if ( !pipe->f_op || !pipe->f_op->write ) |
181 | goto fail_fput; | 190 | goto fail_fput; |
182 | sbi->pipe = pipe; | 191 | sbi->pipe = pipe; |
192 | sbi->catatonic = 0; | ||
183 | 193 | ||
184 | /* | 194 | /* |
185 | * Success! Install the root dentry now to indicate completion. | 195 | * Success! Install the root dentry now to indicate completion. |
@@ -198,6 +208,8 @@ fail_iput: | |||
198 | iput(root_inode); | 208 | iput(root_inode); |
199 | fail_free: | 209 | fail_free: |
200 | kfree(sbi); | 210 | kfree(sbi); |
211 | s->s_fs_info = NULL; | ||
212 | kill_anon_super(s); | ||
201 | fail_unlock: | 213 | fail_unlock: |
202 | return -EINVAL; | 214 | return -EINVAL; |
203 | } | 215 | } |
diff --git a/fs/autofs/waitq.c b/fs/autofs/waitq.c index 633f628005b4..19a9cafb5ddf 100644 --- a/fs/autofs/waitq.c +++ b/fs/autofs/waitq.c | |||
@@ -41,6 +41,7 @@ void autofs_catatonic_mode(struct autofs_sb_info *sbi) | |||
41 | wq = nwq; | 41 | wq = nwq; |
42 | } | 42 | } |
43 | fput(sbi->pipe); /* Close the pipe */ | 43 | fput(sbi->pipe); /* Close the pipe */ |
44 | sbi->pipe = NULL; | ||
44 | autofs_hash_dputall(&sbi->dirhash); /* Remove all dentry pointers */ | 45 | autofs_hash_dputall(&sbi->dirhash); /* Remove all dentry pointers */ |
45 | } | 46 | } |
46 | 47 | ||
diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c index 51fd8595bf85..ce7c0f1dd529 100644 --- a/fs/autofs4/inode.c +++ b/fs/autofs4/inode.c | |||
@@ -99,6 +99,9 @@ static void autofs4_force_release(struct autofs_sb_info *sbi) | |||
99 | struct dentry *this_parent = sbi->sb->s_root; | 99 | struct dentry *this_parent = sbi->sb->s_root; |
100 | struct list_head *next; | 100 | struct list_head *next; |
101 | 101 | ||
102 | if (!sbi->sb->s_root) | ||
103 | return; | ||
104 | |||
102 | spin_lock(&dcache_lock); | 105 | spin_lock(&dcache_lock); |
103 | repeat: | 106 | repeat: |
104 | next = this_parent->d_subdirs.next; | 107 | next = this_parent->d_subdirs.next; |
@@ -146,6 +149,14 @@ void autofs4_kill_sb(struct super_block *sb) | |||
146 | { | 149 | { |
147 | struct autofs_sb_info *sbi = autofs4_sbi(sb); | 150 | struct autofs_sb_info *sbi = autofs4_sbi(sb); |
148 | 151 | ||
152 | /* | ||
153 | * In the event of a failure in get_sb_nodev the superblock | ||
154 | * info is not present so nothing else has been setup, so | ||
155 | * just exit when we are called from deactivate_super. | ||
156 | */ | ||
157 | if (!sbi) | ||
158 | return; | ||
159 | |||
149 | sb->s_fs_info = NULL; | 160 | sb->s_fs_info = NULL; |
150 | 161 | ||
151 | if ( !sbi->catatonic ) | 162 | if ( !sbi->catatonic ) |
@@ -310,7 +321,8 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent) | |||
310 | s->s_fs_info = sbi; | 321 | s->s_fs_info = sbi; |
311 | sbi->magic = AUTOFS_SBI_MAGIC; | 322 | sbi->magic = AUTOFS_SBI_MAGIC; |
312 | sbi->pipefd = -1; | 323 | sbi->pipefd = -1; |
313 | sbi->catatonic = 0; | 324 | sbi->pipe = NULL; |
325 | sbi->catatonic = 1; | ||
314 | sbi->exp_timeout = 0; | 326 | sbi->exp_timeout = 0; |
315 | sbi->oz_pgrp = process_group(current); | 327 | sbi->oz_pgrp = process_group(current); |
316 | sbi->sb = s; | 328 | sbi->sb = s; |
@@ -388,6 +400,7 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent) | |||
388 | goto fail_fput; | 400 | goto fail_fput; |
389 | sbi->pipe = pipe; | 401 | sbi->pipe = pipe; |
390 | sbi->pipefd = pipefd; | 402 | sbi->pipefd = pipefd; |
403 | sbi->catatonic = 0; | ||
391 | 404 | ||
392 | /* | 405 | /* |
393 | * Success! Install the root dentry now to indicate completion. | 406 | * Success! Install the root dentry now to indicate completion. |
@@ -412,6 +425,8 @@ fail_ino: | |||
412 | kfree(ino); | 425 | kfree(ino); |
413 | fail_free: | 426 | fail_free: |
414 | kfree(sbi); | 427 | kfree(sbi); |
428 | s->s_fs_info = NULL; | ||
429 | kill_anon_super(s); | ||
415 | fail_unlock: | 430 | fail_unlock: |
416 | return -EINVAL; | 431 | return -EINVAL; |
417 | } | 432 | } |
diff --git a/fs/autofs4/waitq.c b/fs/autofs4/waitq.c index c0a6c8d445c7..1e4a539f4417 100644 --- a/fs/autofs4/waitq.c +++ b/fs/autofs4/waitq.c | |||
@@ -41,10 +41,8 @@ void autofs4_catatonic_mode(struct autofs_sb_info *sbi) | |||
41 | wake_up_interruptible(&wq->queue); | 41 | wake_up_interruptible(&wq->queue); |
42 | wq = nwq; | 42 | wq = nwq; |
43 | } | 43 | } |
44 | if (sbi->pipe) { | 44 | fput(sbi->pipe); /* Close the pipe */ |
45 | fput(sbi->pipe); /* Close the pipe */ | 45 | sbi->pipe = NULL; |
46 | sbi->pipe = NULL; | ||
47 | } | ||
48 | } | 46 | } |
49 | 47 | ||
50 | static int autofs4_write(struct file *file, const void *addr, int bytes) | 48 | static int autofs4_write(struct file *file, const void *addr, int bytes) |
diff --git a/fs/block_dev.c b/fs/block_dev.c index bc8f27cc4483..36c0e7af9d0f 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c | |||
@@ -642,34 +642,47 @@ static void free_bd_holder(struct bd_holder *bo) | |||
642 | } | 642 | } |
643 | 643 | ||
644 | /** | 644 | /** |
645 | * find_bd_holder - find matching struct bd_holder from the block device | ||
646 | * | ||
647 | * @bdev: struct block device to be searched | ||
648 | * @bo: target struct bd_holder | ||
649 | * | ||
650 | * Returns matching entry with @bo in @bdev->bd_holder_list. | ||
651 | * If found, increment the reference count and return the pointer. | ||
652 | * If not found, returns NULL. | ||
653 | */ | ||
654 | static struct bd_holder *find_bd_holder(struct block_device *bdev, | ||
655 | struct bd_holder *bo) | ||
656 | { | ||
657 | struct bd_holder *tmp; | ||
658 | |||
659 | list_for_each_entry(tmp, &bdev->bd_holder_list, list) | ||
660 | if (tmp->sdir == bo->sdir) { | ||
661 | tmp->count++; | ||
662 | return tmp; | ||
663 | } | ||
664 | |||
665 | return NULL; | ||
666 | } | ||
667 | |||
668 | /** | ||
645 | * add_bd_holder - create sysfs symlinks for bd_claim() relationship | 669 | * add_bd_holder - create sysfs symlinks for bd_claim() relationship |
646 | * | 670 | * |
647 | * @bdev: block device to be bd_claimed | 671 | * @bdev: block device to be bd_claimed |
648 | * @bo: preallocated and initialized by alloc_bd_holder() | 672 | * @bo: preallocated and initialized by alloc_bd_holder() |
649 | * | 673 | * |
650 | * If there is no matching entry with @bo in @bdev->bd_holder_list, | 674 | * Add @bo to @bdev->bd_holder_list, create symlinks. |
651 | * add @bo to the list, create symlinks. | ||
652 | * | 675 | * |
653 | * Returns 0 if symlinks are created or already there. | 676 | * Returns 0 if symlinks are created. |
654 | * Returns -ve if something fails and @bo can be freed. | 677 | * Returns -ve if something fails. |
655 | */ | 678 | */ |
656 | static int add_bd_holder(struct block_device *bdev, struct bd_holder *bo) | 679 | static int add_bd_holder(struct block_device *bdev, struct bd_holder *bo) |
657 | { | 680 | { |
658 | struct bd_holder *tmp; | ||
659 | int ret; | 681 | int ret; |
660 | 682 | ||
661 | if (!bo) | 683 | if (!bo) |
662 | return -EINVAL; | 684 | return -EINVAL; |
663 | 685 | ||
664 | list_for_each_entry(tmp, &bdev->bd_holder_list, list) { | ||
665 | if (tmp->sdir == bo->sdir) { | ||
666 | tmp->count++; | ||
667 | /* We've already done what we need to do here. */ | ||
668 | free_bd_holder(bo); | ||
669 | return 0; | ||
670 | } | ||
671 | } | ||
672 | |||
673 | if (!bd_holder_grab_dirs(bdev, bo)) | 686 | if (!bd_holder_grab_dirs(bdev, bo)) |
674 | return -EBUSY; | 687 | return -EBUSY; |
675 | 688 | ||
@@ -740,7 +753,7 @@ static int bd_claim_by_kobject(struct block_device *bdev, void *holder, | |||
740 | struct kobject *kobj) | 753 | struct kobject *kobj) |
741 | { | 754 | { |
742 | int res; | 755 | int res; |
743 | struct bd_holder *bo; | 756 | struct bd_holder *bo, *found; |
744 | 757 | ||
745 | if (!kobj) | 758 | if (!kobj) |
746 | return -EINVAL; | 759 | return -EINVAL; |
@@ -751,9 +764,16 @@ static int bd_claim_by_kobject(struct block_device *bdev, void *holder, | |||
751 | 764 | ||
752 | mutex_lock_nested(&bdev->bd_mutex, BD_MUTEX_PARTITION); | 765 | mutex_lock_nested(&bdev->bd_mutex, BD_MUTEX_PARTITION); |
753 | res = bd_claim(bdev, holder); | 766 | res = bd_claim(bdev, holder); |
754 | if (res == 0) | 767 | if (res == 0) { |
755 | res = add_bd_holder(bdev, bo); | 768 | found = find_bd_holder(bdev, bo); |
756 | if (res) | 769 | if (found == NULL) { |
770 | res = add_bd_holder(bdev, bo); | ||
771 | if (res) | ||
772 | bd_release(bdev); | ||
773 | } | ||
774 | } | ||
775 | |||
776 | if (res || found) | ||
757 | free_bd_holder(bo); | 777 | free_bd_holder(bo); |
758 | mutex_unlock(&bdev->bd_mutex); | 778 | mutex_unlock(&bdev->bd_mutex); |
759 | 779 | ||
@@ -1131,6 +1151,8 @@ static int blkdev_open(struct inode * inode, struct file * filp) | |||
1131 | filp->f_flags |= O_LARGEFILE; | 1151 | filp->f_flags |= O_LARGEFILE; |
1132 | 1152 | ||
1133 | bdev = bd_acquire(inode); | 1153 | bdev = bd_acquire(inode); |
1154 | if (bdev == NULL) | ||
1155 | return -ENOMEM; | ||
1134 | 1156 | ||
1135 | res = do_open(bdev, filp, BD_MUTEX_NORMAL); | 1157 | res = do_open(bdev, filp, BD_MUTEX_NORMAL); |
1136 | if (res) | 1158 | if (res) |
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index 1eb9a2ec0a3b..0b3c37ef52e0 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES | |||
@@ -1,6 +1,11 @@ | |||
1 | Version 1.46 | 1 | Version 1.46 |
2 | ------------ | 2 | ------------ |
3 | Support deep tree mounts. Better support OS/2, Win9x (DOS) time stamps. | 3 | Support deep tree mounts. Better support OS/2, Win9x (DOS) time stamps. |
4 | Allow null user to be specified on mount ("username="). Do not return | ||
5 | EINVAL on readdir when filldir fails due to overwritten blocksize | ||
6 | (fixes FC problem). Return error in rename 2nd attempt retry (ie report | ||
7 | if rename by handle also fails, after rename by path fails, we were | ||
8 | not reporting whether the retry worked or not). | ||
4 | 9 | ||
5 | Version 1.45 | 10 | Version 1.45 |
6 | ------------ | 11 | ------------ |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 4093d5332930..71f77914ce93 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -822,10 +822,13 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) | |||
822 | } else if (strnicmp(data, "nouser_xattr",12) == 0) { | 822 | } else if (strnicmp(data, "nouser_xattr",12) == 0) { |
823 | vol->no_xattr = 1; | 823 | vol->no_xattr = 1; |
824 | } else if (strnicmp(data, "user", 4) == 0) { | 824 | } else if (strnicmp(data, "user", 4) == 0) { |
825 | if (!value || !*value) { | 825 | if (!value) { |
826 | printk(KERN_WARNING | 826 | printk(KERN_WARNING |
827 | "CIFS: invalid or missing username\n"); | 827 | "CIFS: invalid or missing username\n"); |
828 | return 1; /* needs_arg; */ | 828 | return 1; /* needs_arg; */ |
829 | } else if(!*value) { | ||
830 | /* null user, ie anonymous, authentication */ | ||
831 | vol->nullauth = 1; | ||
829 | } | 832 | } |
830 | if (strnlen(value, 200) < 200) { | 833 | if (strnlen(value, 200) < 200) { |
831 | vol->username = value; | 834 | vol->username = value; |
@@ -1642,6 +1645,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1642 | /* BB fixme parse for domain name here */ | 1645 | /* BB fixme parse for domain name here */ |
1643 | cFYI(1, ("Username: %s ", volume_info.username)); | 1646 | cFYI(1, ("Username: %s ", volume_info.username)); |
1644 | 1647 | ||
1648 | } else if (volume_info.nullauth) { | ||
1649 | cFYI(1,("null user")); | ||
1645 | } else { | 1650 | } else { |
1646 | cifserror("No username specified"); | 1651 | cifserror("No username specified"); |
1647 | /* In userspace mount helper we can get user name from alternate | 1652 | /* In userspace mount helper we can get user name from alternate |
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 976a691c5a68..2436ed8fc840 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
@@ -492,10 +492,14 @@ int cifs_close(struct inode *inode, struct file *file) | |||
492 | the struct would be in each open file, | 492 | the struct would be in each open file, |
493 | but this should give enough time to | 493 | but this should give enough time to |
494 | clear the socket */ | 494 | clear the socket */ |
495 | cERROR(1,("close with pending writes")); | 495 | #ifdef CONFIG_CIFS_DEBUG2 |
496 | cFYI(1,("close delay, write pending")); | ||
497 | #endif /* DEBUG2 */ | ||
496 | msleep(timeout); | 498 | msleep(timeout); |
497 | timeout *= 4; | 499 | timeout *= 4; |
498 | } | 500 | } |
501 | if(atomic_read(&pSMBFile->wrtPending)) | ||
502 | cERROR(1,("close with pending writes")); | ||
499 | rc = CIFSSMBClose(xid, pTcon, | 503 | rc = CIFSSMBClose(xid, pTcon, |
500 | pSMBFile->netfid); | 504 | pSMBFile->netfid); |
501 | } | 505 | } |
@@ -1806,13 +1810,6 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, | |||
1806 | } | 1810 | } |
1807 | if ((rc < 0) || (smb_read_data == NULL)) { | 1811 | if ((rc < 0) || (smb_read_data == NULL)) { |
1808 | cFYI(1, ("Read error in readpages: %d", rc)); | 1812 | cFYI(1, ("Read error in readpages: %d", rc)); |
1809 | /* clean up remaing pages off list */ | ||
1810 | while (!list_empty(page_list) && (i < num_pages)) { | ||
1811 | page = list_entry(page_list->prev, struct page, | ||
1812 | lru); | ||
1813 | list_del(&page->lru); | ||
1814 | page_cache_release(page); | ||
1815 | } | ||
1816 | break; | 1813 | break; |
1817 | } else if (bytes_read > 0) { | 1814 | } else if (bytes_read > 0) { |
1818 | pSMBr = (struct smb_com_read_rsp *)smb_read_data; | 1815 | pSMBr = (struct smb_com_read_rsp *)smb_read_data; |
@@ -1831,13 +1828,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, | |||
1831 | this case is ok - if we are at server EOF | 1828 | this case is ok - if we are at server EOF |
1832 | we will hit it on next read */ | 1829 | we will hit it on next read */ |
1833 | 1830 | ||
1834 | /* while (!list_empty(page_list) && (i < num_pages)) { | 1831 | /* break; */ |
1835 | page = list_entry(page_list->prev, | ||
1836 | struct page, list); | ||
1837 | list_del(&page->list); | ||
1838 | page_cache_release(page); | ||
1839 | } | ||
1840 | break; */ | ||
1841 | } | 1832 | } |
1842 | } else { | 1833 | } else { |
1843 | cFYI(1, ("No bytes read (%d) at offset %lld . " | 1834 | cFYI(1, ("No bytes read (%d) at offset %lld . " |
@@ -1845,14 +1836,6 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, | |||
1845 | bytes_read, offset)); | 1836 | bytes_read, offset)); |
1846 | /* BB turn off caching and do new lookup on | 1837 | /* BB turn off caching and do new lookup on |
1847 | file size at server? */ | 1838 | file size at server? */ |
1848 | while (!list_empty(page_list) && (i < num_pages)) { | ||
1849 | page = list_entry(page_list->prev, struct page, | ||
1850 | lru); | ||
1851 | list_del(&page->lru); | ||
1852 | |||
1853 | /* BB removeme - replace with zero of page? */ | ||
1854 | page_cache_release(page); | ||
1855 | } | ||
1856 | break; | 1839 | break; |
1857 | } | 1840 | } |
1858 | if (smb_read_data) { | 1841 | if (smb_read_data) { |
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 35d54bb0869a..1ad8c9fcc742 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -885,10 +885,14 @@ int cifs_rename(struct inode *source_inode, struct dentry *source_direntry, | |||
885 | kmalloc(2 * sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL); | 885 | kmalloc(2 * sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL); |
886 | if (info_buf_source != NULL) { | 886 | if (info_buf_source != NULL) { |
887 | info_buf_target = info_buf_source + 1; | 887 | info_buf_target = info_buf_source + 1; |
888 | rc = CIFSSMBUnixQPathInfo(xid, pTcon, fromName, | 888 | if (pTcon->ses->capabilities & CAP_UNIX) |
889 | info_buf_source, cifs_sb_source->local_nls, | 889 | rc = CIFSSMBUnixQPathInfo(xid, pTcon, fromName, |
890 | cifs_sb_source->mnt_cifs_flags & | 890 | info_buf_source, |
891 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 891 | cifs_sb_source->local_nls, |
892 | cifs_sb_source->mnt_cifs_flags & | ||
893 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
894 | /* else rc is still EEXIST so will fall through to | ||
895 | unlink the target and retry rename */ | ||
892 | if (rc == 0) { | 896 | if (rc == 0) { |
893 | rc = CIFSSMBUnixQPathInfo(xid, pTcon, toName, | 897 | rc = CIFSSMBUnixQPathInfo(xid, pTcon, toName, |
894 | info_buf_target, | 898 | info_buf_target, |
@@ -937,7 +941,7 @@ int cifs_rename(struct inode *source_inode, struct dentry *source_direntry, | |||
937 | cifs_sb_source->mnt_cifs_flags & | 941 | cifs_sb_source->mnt_cifs_flags & |
938 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 942 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
939 | if (rc==0) { | 943 | if (rc==0) { |
940 | CIFSSMBRenameOpenFile(xid, pTcon, netfid, toName, | 944 | rc = CIFSSMBRenameOpenFile(xid, pTcon, netfid, toName, |
941 | cifs_sb_source->local_nls, | 945 | cifs_sb_source->local_nls, |
942 | cifs_sb_source->mnt_cifs_flags & | 946 | cifs_sb_source->mnt_cifs_flags & |
943 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 947 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
@@ -1085,8 +1089,10 @@ int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry, | |||
1085 | struct kstat *stat) | 1089 | struct kstat *stat) |
1086 | { | 1090 | { |
1087 | int err = cifs_revalidate(dentry); | 1091 | int err = cifs_revalidate(dentry); |
1088 | if (!err) | 1092 | if (!err) { |
1089 | generic_fillattr(dentry->d_inode, stat); | 1093 | generic_fillattr(dentry->d_inode, stat); |
1094 | stat->blksize = CIFS_MAX_MSGSIZE; | ||
1095 | } | ||
1090 | return err; | 1096 | return err; |
1091 | } | 1097 | } |
1092 | 1098 | ||
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index b5b0a2a41bef..ed18c3965f7b 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c | |||
@@ -896,6 +896,10 @@ static int cifs_filldir(char *pfindEntry, struct file *file, | |||
896 | tmp_inode->i_ino,obj_type); | 896 | tmp_inode->i_ino,obj_type); |
897 | if(rc) { | 897 | if(rc) { |
898 | cFYI(1,("filldir rc = %d",rc)); | 898 | cFYI(1,("filldir rc = %d",rc)); |
899 | /* we can not return filldir errors to the caller | ||
900 | since they are "normal" when the stat blocksize | ||
901 | is too small - we return remapped error instead */ | ||
902 | rc = -EOVERFLOW; | ||
899 | } | 903 | } |
900 | 904 | ||
901 | dput(tmp_dentry); | 905 | dput(tmp_dentry); |
@@ -1074,6 +1078,11 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir) | |||
1074 | we want to check for that here? */ | 1078 | we want to check for that here? */ |
1075 | rc = cifs_filldir(current_entry, file, | 1079 | rc = cifs_filldir(current_entry, file, |
1076 | filldir, direntry, tmp_buf, max_len); | 1080 | filldir, direntry, tmp_buf, max_len); |
1081 | if(rc == -EOVERFLOW) { | ||
1082 | rc = 0; | ||
1083 | break; | ||
1084 | } | ||
1085 | |||
1077 | file->f_pos++; | 1086 | file->f_pos++; |
1078 | if(file->f_pos == | 1087 | if(file->f_pos == |
1079 | cifsFile->srch_inf.index_of_last_entry) { | 1088 | cifsFile->srch_inf.index_of_last_entry) { |
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c index a8a083543ba0..bbdda99dce61 100644 --- a/fs/cifs/sess.c +++ b/fs/cifs/sess.c | |||
@@ -90,7 +90,9 @@ static void unicode_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses, | |||
90 | } */ | 90 | } */ |
91 | /* copy user */ | 91 | /* copy user */ |
92 | if(ses->userName == NULL) { | 92 | if(ses->userName == NULL) { |
93 | /* BB what about null user mounts - check that we do this BB */ | 93 | /* null user mount */ |
94 | *bcc_ptr = 0; | ||
95 | *(bcc_ptr+1) = 0; | ||
94 | } else { /* 300 should be long enough for any conceivable user name */ | 96 | } else { /* 300 should be long enough for any conceivable user name */ |
95 | bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, ses->userName, | 97 | bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, ses->userName, |
96 | 300, nls_cp); | 98 | 300, nls_cp); |
@@ -98,10 +100,13 @@ static void unicode_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses, | |||
98 | bcc_ptr += 2 * bytes_ret; | 100 | bcc_ptr += 2 * bytes_ret; |
99 | bcc_ptr += 2; /* account for null termination */ | 101 | bcc_ptr += 2; /* account for null termination */ |
100 | /* copy domain */ | 102 | /* copy domain */ |
101 | if(ses->domainName == NULL) | 103 | if(ses->domainName == NULL) { |
102 | bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, | 104 | /* Sending null domain better than using a bogus domain name (as |
103 | "CIFS_LINUX_DOM", 32, nls_cp); | 105 | we did briefly in 2.6.18) since server will use its default */ |
104 | else | 106 | *bcc_ptr = 0; |
107 | *(bcc_ptr+1) = 0; | ||
108 | bytes_ret = 0; | ||
109 | } else | ||
105 | bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, ses->domainName, | 110 | bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, ses->domainName, |
106 | 256, nls_cp); | 111 | 256, nls_cp); |
107 | bcc_ptr += 2 * bytes_ret; | 112 | bcc_ptr += 2 * bytes_ret; |
@@ -144,13 +149,11 @@ static void ascii_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses, | |||
144 | 149 | ||
145 | /* copy domain */ | 150 | /* copy domain */ |
146 | 151 | ||
147 | if(ses->domainName == NULL) { | 152 | if(ses->domainName != NULL) { |
148 | strcpy(bcc_ptr, "CIFS_LINUX_DOM"); | ||
149 | bcc_ptr += 14; /* strlen(CIFS_LINUX_DOM) */ | ||
150 | } else { | ||
151 | strncpy(bcc_ptr, ses->domainName, 256); | 153 | strncpy(bcc_ptr, ses->domainName, 256); |
152 | bcc_ptr += strnlen(ses->domainName, 256); | 154 | bcc_ptr += strnlen(ses->domainName, 256); |
153 | } | 155 | } /* else we will send a null domain name |
156 | so the server will default to its own domain */ | ||
154 | *bcc_ptr = 0; | 157 | *bcc_ptr = 0; |
155 | bcc_ptr++; | 158 | bcc_ptr++; |
156 | 159 | ||
diff --git a/fs/compat.c b/fs/compat.c index 50624d4a70c6..8d0a0018a7d2 100644 --- a/fs/compat.c +++ b/fs/compat.c | |||
@@ -1835,9 +1835,12 @@ asmlinkage long compat_sys_pselect7(int n, compat_ulong_t __user *inp, | |||
1835 | 1835 | ||
1836 | } while (!ret && !timeout && tsp && (ts.tv_sec || ts.tv_nsec)); | 1836 | } while (!ret && !timeout && tsp && (ts.tv_sec || ts.tv_nsec)); |
1837 | 1837 | ||
1838 | if (ret == 0 && tsp && !(current->personality & STICKY_TIMEOUTS)) { | 1838 | if (tsp) { |
1839 | struct compat_timespec rts; | 1839 | struct compat_timespec rts; |
1840 | 1840 | ||
1841 | if (current->personality & STICKY_TIMEOUTS) | ||
1842 | goto sticky; | ||
1843 | |||
1841 | rts.tv_sec = timeout / HZ; | 1844 | rts.tv_sec = timeout / HZ; |
1842 | rts.tv_nsec = (timeout % HZ) * (NSEC_PER_SEC/HZ); | 1845 | rts.tv_nsec = (timeout % HZ) * (NSEC_PER_SEC/HZ); |
1843 | if (rts.tv_nsec >= NSEC_PER_SEC) { | 1846 | if (rts.tv_nsec >= NSEC_PER_SEC) { |
@@ -1846,8 +1849,19 @@ asmlinkage long compat_sys_pselect7(int n, compat_ulong_t __user *inp, | |||
1846 | } | 1849 | } |
1847 | if (compat_timespec_compare(&rts, &ts) >= 0) | 1850 | if (compat_timespec_compare(&rts, &ts) >= 0) |
1848 | rts = ts; | 1851 | rts = ts; |
1849 | if (copy_to_user(tsp, &rts, sizeof(rts))) | 1852 | if (copy_to_user(tsp, &rts, sizeof(rts))) { |
1850 | ret = -EFAULT; | 1853 | sticky: |
1854 | /* | ||
1855 | * If an application puts its timeval in read-only | ||
1856 | * memory, we don't want the Linux-specific update to | ||
1857 | * the timeval to cause a fault after the select has | ||
1858 | * completed successfully. However, because we're not | ||
1859 | * updating the timeval, we can't restart the system | ||
1860 | * call. | ||
1861 | */ | ||
1862 | if (ret == -ERESTARTNOHAND) | ||
1863 | ret = -EINTR; | ||
1864 | } | ||
1851 | } | 1865 | } |
1852 | 1866 | ||
1853 | if (ret == -ERESTARTNOHAND) { | 1867 | if (ret == -ERESTARTNOHAND) { |
diff --git a/fs/dcache.c b/fs/dcache.c index 2bac4ba1d1d3..fd4a428998ef 100644 --- a/fs/dcache.c +++ b/fs/dcache.c | |||
@@ -478,11 +478,12 @@ static void prune_dcache(int count, struct super_block *sb) | |||
478 | up_read(s_umount); | 478 | up_read(s_umount); |
479 | } | 479 | } |
480 | spin_unlock(&dentry->d_lock); | 480 | spin_unlock(&dentry->d_lock); |
481 | /* Cannot remove the first dentry, and it isn't appropriate | 481 | /* |
482 | * to move it to the head of the list, so give up, and try | 482 | * Insert dentry at the head of the list as inserting at the |
483 | * later | 483 | * tail leads to a cycle. |
484 | */ | 484 | */ |
485 | break; | 485 | list_add(&dentry->d_lru, &dentry_unused); |
486 | dentry_stat.nr_unused++; | ||
486 | } | 487 | } |
487 | spin_unlock(&dcache_lock); | 488 | spin_unlock(&dcache_lock); |
488 | } | 489 | } |
@@ -556,6 +557,7 @@ repeat: | |||
556 | static void shrink_dcache_for_umount_subtree(struct dentry *dentry) | 557 | static void shrink_dcache_for_umount_subtree(struct dentry *dentry) |
557 | { | 558 | { |
558 | struct dentry *parent; | 559 | struct dentry *parent; |
560 | unsigned detached = 0; | ||
559 | 561 | ||
560 | BUG_ON(!IS_ROOT(dentry)); | 562 | BUG_ON(!IS_ROOT(dentry)); |
561 | 563 | ||
@@ -620,7 +622,7 @@ static void shrink_dcache_for_umount_subtree(struct dentry *dentry) | |||
620 | atomic_dec(&parent->d_count); | 622 | atomic_dec(&parent->d_count); |
621 | 623 | ||
622 | list_del(&dentry->d_u.d_child); | 624 | list_del(&dentry->d_u.d_child); |
623 | dentry_stat.nr_dentry--; /* For d_free, below */ | 625 | detached++; |
624 | 626 | ||
625 | inode = dentry->d_inode; | 627 | inode = dentry->d_inode; |
626 | if (inode) { | 628 | if (inode) { |
@@ -638,7 +640,7 @@ static void shrink_dcache_for_umount_subtree(struct dentry *dentry) | |||
638 | * otherwise we ascend to the parent and move to the | 640 | * otherwise we ascend to the parent and move to the |
639 | * next sibling if there is one */ | 641 | * next sibling if there is one */ |
640 | if (!parent) | 642 | if (!parent) |
641 | return; | 643 | goto out; |
642 | 644 | ||
643 | dentry = parent; | 645 | dentry = parent; |
644 | 646 | ||
@@ -647,6 +649,11 @@ static void shrink_dcache_for_umount_subtree(struct dentry *dentry) | |||
647 | dentry = list_entry(dentry->d_subdirs.next, | 649 | dentry = list_entry(dentry->d_subdirs.next, |
648 | struct dentry, d_u.d_child); | 650 | struct dentry, d_u.d_child); |
649 | } | 651 | } |
652 | out: | ||
653 | /* several dentries were freed, need to correct nr_dentry */ | ||
654 | spin_lock(&dcache_lock); | ||
655 | dentry_stat.nr_dentry -= detached; | ||
656 | spin_unlock(&dcache_lock); | ||
650 | } | 657 | } |
651 | 658 | ||
652 | /* | 659 | /* |
@@ -1469,23 +1476,21 @@ static void switch_names(struct dentry *dentry, struct dentry *target) | |||
1469 | * deleted it. | 1476 | * deleted it. |
1470 | */ | 1477 | */ |
1471 | 1478 | ||
1472 | /** | 1479 | /* |
1473 | * d_move - move a dentry | 1480 | * d_move_locked - move a dentry |
1474 | * @dentry: entry to move | 1481 | * @dentry: entry to move |
1475 | * @target: new dentry | 1482 | * @target: new dentry |
1476 | * | 1483 | * |
1477 | * Update the dcache to reflect the move of a file name. Negative | 1484 | * Update the dcache to reflect the move of a file name. Negative |
1478 | * dcache entries should not be moved in this way. | 1485 | * dcache entries should not be moved in this way. |
1479 | */ | 1486 | */ |
1480 | 1487 | static void d_move_locked(struct dentry * dentry, struct dentry * target) | |
1481 | void d_move(struct dentry * dentry, struct dentry * target) | ||
1482 | { | 1488 | { |
1483 | struct hlist_head *list; | 1489 | struct hlist_head *list; |
1484 | 1490 | ||
1485 | if (!dentry->d_inode) | 1491 | if (!dentry->d_inode) |
1486 | printk(KERN_WARNING "VFS: moving negative dcache entry\n"); | 1492 | printk(KERN_WARNING "VFS: moving negative dcache entry\n"); |
1487 | 1493 | ||
1488 | spin_lock(&dcache_lock); | ||
1489 | write_seqlock(&rename_lock); | 1494 | write_seqlock(&rename_lock); |
1490 | /* | 1495 | /* |
1491 | * XXXX: do we really need to take target->d_lock? | 1496 | * XXXX: do we really need to take target->d_lock? |
@@ -1536,7 +1541,81 @@ already_unhashed: | |||
1536 | fsnotify_d_move(dentry); | 1541 | fsnotify_d_move(dentry); |
1537 | spin_unlock(&dentry->d_lock); | 1542 | spin_unlock(&dentry->d_lock); |
1538 | write_sequnlock(&rename_lock); | 1543 | write_sequnlock(&rename_lock); |
1544 | } | ||
1545 | |||
1546 | /** | ||
1547 | * d_move - move a dentry | ||
1548 | * @dentry: entry to move | ||
1549 | * @target: new dentry | ||
1550 | * | ||
1551 | * Update the dcache to reflect the move of a file name. Negative | ||
1552 | * dcache entries should not be moved in this way. | ||
1553 | */ | ||
1554 | |||
1555 | void d_move(struct dentry * dentry, struct dentry * target) | ||
1556 | { | ||
1557 | spin_lock(&dcache_lock); | ||
1558 | d_move_locked(dentry, target); | ||
1559 | spin_unlock(&dcache_lock); | ||
1560 | } | ||
1561 | |||
1562 | /* | ||
1563 | * Helper that returns 1 if p1 is a parent of p2, else 0 | ||
1564 | */ | ||
1565 | static int d_isparent(struct dentry *p1, struct dentry *p2) | ||
1566 | { | ||
1567 | struct dentry *p; | ||
1568 | |||
1569 | for (p = p2; p->d_parent != p; p = p->d_parent) { | ||
1570 | if (p->d_parent == p1) | ||
1571 | return 1; | ||
1572 | } | ||
1573 | return 0; | ||
1574 | } | ||
1575 | |||
1576 | /* | ||
1577 | * This helper attempts to cope with remotely renamed directories | ||
1578 | * | ||
1579 | * It assumes that the caller is already holding | ||
1580 | * dentry->d_parent->d_inode->i_mutex and the dcache_lock | ||
1581 | * | ||
1582 | * Note: If ever the locking in lock_rename() changes, then please | ||
1583 | * remember to update this too... | ||
1584 | * | ||
1585 | * On return, dcache_lock will have been unlocked. | ||
1586 | */ | ||
1587 | static struct dentry *__d_unalias(struct dentry *dentry, struct dentry *alias) | ||
1588 | { | ||
1589 | struct mutex *m1 = NULL, *m2 = NULL; | ||
1590 | struct dentry *ret; | ||
1591 | |||
1592 | /* If alias and dentry share a parent, then no extra locks required */ | ||
1593 | if (alias->d_parent == dentry->d_parent) | ||
1594 | goto out_unalias; | ||
1595 | |||
1596 | /* Check for loops */ | ||
1597 | ret = ERR_PTR(-ELOOP); | ||
1598 | if (d_isparent(alias, dentry)) | ||
1599 | goto out_err; | ||
1600 | |||
1601 | /* See lock_rename() */ | ||
1602 | ret = ERR_PTR(-EBUSY); | ||
1603 | if (!mutex_trylock(&dentry->d_sb->s_vfs_rename_mutex)) | ||
1604 | goto out_err; | ||
1605 | m1 = &dentry->d_sb->s_vfs_rename_mutex; | ||
1606 | if (!mutex_trylock(&alias->d_parent->d_inode->i_mutex)) | ||
1607 | goto out_err; | ||
1608 | m2 = &alias->d_parent->d_inode->i_mutex; | ||
1609 | out_unalias: | ||
1610 | d_move_locked(alias, dentry); | ||
1611 | ret = alias; | ||
1612 | out_err: | ||
1539 | spin_unlock(&dcache_lock); | 1613 | spin_unlock(&dcache_lock); |
1614 | if (m2) | ||
1615 | mutex_unlock(m2); | ||
1616 | if (m1) | ||
1617 | mutex_unlock(m1); | ||
1618 | return ret; | ||
1540 | } | 1619 | } |
1541 | 1620 | ||
1542 | /* | 1621 | /* |
@@ -1581,7 +1660,7 @@ static void __d_materialise_dentry(struct dentry *dentry, struct dentry *anon) | |||
1581 | */ | 1660 | */ |
1582 | struct dentry *d_materialise_unique(struct dentry *dentry, struct inode *inode) | 1661 | struct dentry *d_materialise_unique(struct dentry *dentry, struct inode *inode) |
1583 | { | 1662 | { |
1584 | struct dentry *alias, *actual; | 1663 | struct dentry *actual; |
1585 | 1664 | ||
1586 | BUG_ON(!d_unhashed(dentry)); | 1665 | BUG_ON(!d_unhashed(dentry)); |
1587 | 1666 | ||
@@ -1593,26 +1672,27 @@ struct dentry *d_materialise_unique(struct dentry *dentry, struct inode *inode) | |||
1593 | goto found_lock; | 1672 | goto found_lock; |
1594 | } | 1673 | } |
1595 | 1674 | ||
1596 | /* See if a disconnected directory already exists as an anonymous root | 1675 | if (S_ISDIR(inode->i_mode)) { |
1597 | * that we should splice into the tree instead */ | 1676 | struct dentry *alias; |
1598 | if (S_ISDIR(inode->i_mode) && (alias = __d_find_alias(inode, 1))) { | 1677 | |
1599 | spin_lock(&alias->d_lock); | 1678 | /* Does an aliased dentry already exist? */ |
1600 | 1679 | alias = __d_find_alias(inode, 0); | |
1601 | /* Is this a mountpoint that we could splice into our tree? */ | 1680 | if (alias) { |
1602 | if (IS_ROOT(alias)) | 1681 | actual = alias; |
1603 | goto connect_mountpoint; | 1682 | /* Is this an anonymous mountpoint that we could splice |
1604 | 1683 | * into our tree? */ | |
1605 | if (alias->d_name.len == dentry->d_name.len && | 1684 | if (IS_ROOT(alias)) { |
1606 | alias->d_parent == dentry->d_parent && | 1685 | spin_lock(&alias->d_lock); |
1607 | memcmp(alias->d_name.name, | 1686 | __d_materialise_dentry(dentry, alias); |
1608 | dentry->d_name.name, | 1687 | __d_drop(alias); |
1609 | dentry->d_name.len) == 0) | 1688 | goto found; |
1610 | goto replace_with_alias; | 1689 | } |
1611 | 1690 | /* Nope, but we must(!) avoid directory aliasing */ | |
1612 | spin_unlock(&alias->d_lock); | 1691 | actual = __d_unalias(dentry, alias); |
1613 | 1692 | if (IS_ERR(actual)) | |
1614 | /* Doh! Seem to be aliasing directories for some reason... */ | 1693 | dput(alias); |
1615 | dput(alias); | 1694 | goto out_nolock; |
1695 | } | ||
1616 | } | 1696 | } |
1617 | 1697 | ||
1618 | /* Add a unique reference */ | 1698 | /* Add a unique reference */ |
@@ -1628,7 +1708,7 @@ found: | |||
1628 | _d_rehash(actual); | 1708 | _d_rehash(actual); |
1629 | spin_unlock(&actual->d_lock); | 1709 | spin_unlock(&actual->d_lock); |
1630 | spin_unlock(&dcache_lock); | 1710 | spin_unlock(&dcache_lock); |
1631 | 1711 | out_nolock: | |
1632 | if (actual == dentry) { | 1712 | if (actual == dentry) { |
1633 | security_d_instantiate(dentry, inode); | 1713 | security_d_instantiate(dentry, inode); |
1634 | return NULL; | 1714 | return NULL; |
@@ -1637,16 +1717,6 @@ found: | |||
1637 | iput(inode); | 1717 | iput(inode); |
1638 | return actual; | 1718 | return actual; |
1639 | 1719 | ||
1640 | /* Convert the anonymous/root alias into an ordinary dentry */ | ||
1641 | connect_mountpoint: | ||
1642 | __d_materialise_dentry(dentry, alias); | ||
1643 | |||
1644 | /* Replace the candidate dentry with the alias in the tree */ | ||
1645 | replace_with_alias: | ||
1646 | __d_drop(alias); | ||
1647 | actual = alias; | ||
1648 | goto found; | ||
1649 | |||
1650 | shouldnt_be_hashed: | 1720 | shouldnt_be_hashed: |
1651 | spin_unlock(&dcache_lock); | 1721 | spin_unlock(&dcache_lock); |
1652 | BUG(); | 1722 | BUG(); |
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c index e77676df6713..137d76c3f90a 100644 --- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/mount.h> | 21 | #include <linux/mount.h> |
22 | #include <linux/pagemap.h> | 22 | #include <linux/pagemap.h> |
23 | #include <linux/init.h> | 23 | #include <linux/init.h> |
24 | #include <linux/kobject.h> | ||
24 | #include <linux/namei.h> | 25 | #include <linux/namei.h> |
25 | #include <linux/debugfs.h> | 26 | #include <linux/debugfs.h> |
26 | 27 | ||
@@ -147,13 +148,13 @@ static int debugfs_create_by_name(const char *name, mode_t mode, | |||
147 | *dentry = NULL; | 148 | *dentry = NULL; |
148 | mutex_lock(&parent->d_inode->i_mutex); | 149 | mutex_lock(&parent->d_inode->i_mutex); |
149 | *dentry = lookup_one_len(name, parent, strlen(name)); | 150 | *dentry = lookup_one_len(name, parent, strlen(name)); |
150 | if (!IS_ERR(dentry)) { | 151 | if (!IS_ERR(*dentry)) { |
151 | if ((mode & S_IFMT) == S_IFDIR) | 152 | if ((mode & S_IFMT) == S_IFDIR) |
152 | error = debugfs_mkdir(parent->d_inode, *dentry, mode); | 153 | error = debugfs_mkdir(parent->d_inode, *dentry, mode); |
153 | else | 154 | else |
154 | error = debugfs_create(parent->d_inode, *dentry, mode); | 155 | error = debugfs_create(parent->d_inode, *dentry, mode); |
155 | } else | 156 | } else |
156 | error = PTR_ERR(dentry); | 157 | error = PTR_ERR(*dentry); |
157 | mutex_unlock(&parent->d_inode->i_mutex); | 158 | mutex_unlock(&parent->d_inode->i_mutex); |
158 | 159 | ||
159 | return error; | 160 | return error; |
diff --git a/fs/dlm/lockspace.c b/fs/dlm/lockspace.c index 109333c8ecb9..f8842ca443c2 100644 --- a/fs/dlm/lockspace.c +++ b/fs/dlm/lockspace.c | |||
@@ -43,6 +43,10 @@ static ssize_t dlm_control_store(struct dlm_ls *ls, const char *buf, size_t len) | |||
43 | ssize_t ret = len; | 43 | ssize_t ret = len; |
44 | int n = simple_strtol(buf, NULL, 0); | 44 | int n = simple_strtol(buf, NULL, 0); |
45 | 45 | ||
46 | ls = dlm_find_lockspace_local(ls->ls_local_handle); | ||
47 | if (!ls) | ||
48 | return -EINVAL; | ||
49 | |||
46 | switch (n) { | 50 | switch (n) { |
47 | case 0: | 51 | case 0: |
48 | dlm_ls_stop(ls); | 52 | dlm_ls_stop(ls); |
@@ -53,6 +57,7 @@ static ssize_t dlm_control_store(struct dlm_ls *ls, const char *buf, size_t len) | |||
53 | default: | 57 | default: |
54 | ret = -EINVAL; | 58 | ret = -EINVAL; |
55 | } | 59 | } |
60 | dlm_put_lockspace(ls); | ||
56 | return ret; | 61 | return ret; |
57 | } | 62 | } |
58 | 63 | ||
@@ -143,6 +148,12 @@ static ssize_t dlm_attr_store(struct kobject *kobj, struct attribute *attr, | |||
143 | return a->store ? a->store(ls, buf, len) : len; | 148 | return a->store ? a->store(ls, buf, len) : len; |
144 | } | 149 | } |
145 | 150 | ||
151 | static void lockspace_kobj_release(struct kobject *k) | ||
152 | { | ||
153 | struct dlm_ls *ls = container_of(k, struct dlm_ls, ls_kobj); | ||
154 | kfree(ls); | ||
155 | } | ||
156 | |||
146 | static struct sysfs_ops dlm_attr_ops = { | 157 | static struct sysfs_ops dlm_attr_ops = { |
147 | .show = dlm_attr_show, | 158 | .show = dlm_attr_show, |
148 | .store = dlm_attr_store, | 159 | .store = dlm_attr_store, |
@@ -151,6 +162,7 @@ static struct sysfs_ops dlm_attr_ops = { | |||
151 | static struct kobj_type dlm_ktype = { | 162 | static struct kobj_type dlm_ktype = { |
152 | .default_attrs = dlm_attrs, | 163 | .default_attrs = dlm_attrs, |
153 | .sysfs_ops = &dlm_attr_ops, | 164 | .sysfs_ops = &dlm_attr_ops, |
165 | .release = lockspace_kobj_release, | ||
154 | }; | 166 | }; |
155 | 167 | ||
156 | static struct kset dlm_kset = { | 168 | static struct kset dlm_kset = { |
@@ -678,7 +690,7 @@ static int release_lockspace(struct dlm_ls *ls, int force) | |||
678 | dlm_clear_members_gone(ls); | 690 | dlm_clear_members_gone(ls); |
679 | kfree(ls->ls_node_array); | 691 | kfree(ls->ls_node_array); |
680 | kobject_unregister(&ls->ls_kobj); | 692 | kobject_unregister(&ls->ls_kobj); |
681 | kfree(ls); | 693 | /* The ls structure will be freed when the kobject is done with */ |
682 | 694 | ||
683 | mutex_lock(&ls_lock); | 695 | mutex_lock(&ls_lock); |
684 | ls_count--; | 696 | ls_count--; |
diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c index ed35a9712fa1..f63a7755fe86 100644 --- a/fs/ecryptfs/crypto.c +++ b/fs/ecryptfs/crypto.c | |||
@@ -94,25 +94,53 @@ static int ecryptfs_calculate_md5(char *dst, | |||
94 | struct ecryptfs_crypt_stat *crypt_stat, | 94 | struct ecryptfs_crypt_stat *crypt_stat, |
95 | char *src, int len) | 95 | char *src, int len) |
96 | { | 96 | { |
97 | int rc = 0; | ||
98 | struct scatterlist sg; | 97 | struct scatterlist sg; |
98 | struct hash_desc desc = { | ||
99 | .tfm = crypt_stat->hash_tfm, | ||
100 | .flags = CRYPTO_TFM_REQ_MAY_SLEEP | ||
101 | }; | ||
102 | int rc = 0; | ||
99 | 103 | ||
100 | mutex_lock(&crypt_stat->cs_md5_tfm_mutex); | 104 | mutex_lock(&crypt_stat->cs_hash_tfm_mutex); |
101 | sg_init_one(&sg, (u8 *)src, len); | 105 | sg_init_one(&sg, (u8 *)src, len); |
102 | if (!crypt_stat->md5_tfm) { | 106 | if (!desc.tfm) { |
103 | crypt_stat->md5_tfm = | 107 | desc.tfm = crypto_alloc_hash(ECRYPTFS_DEFAULT_HASH, 0, |
104 | crypto_alloc_tfm("md5", CRYPTO_TFM_REQ_MAY_SLEEP); | 108 | CRYPTO_ALG_ASYNC); |
105 | if (!crypt_stat->md5_tfm) { | 109 | if (IS_ERR(desc.tfm)) { |
106 | rc = -ENOMEM; | 110 | rc = PTR_ERR(desc.tfm); |
107 | ecryptfs_printk(KERN_ERR, "Error attempting to " | 111 | ecryptfs_printk(KERN_ERR, "Error attempting to " |
108 | "allocate crypto context\n"); | 112 | "allocate crypto context; rc = [%d]\n", |
113 | rc); | ||
109 | goto out; | 114 | goto out; |
110 | } | 115 | } |
116 | crypt_stat->hash_tfm = desc.tfm; | ||
111 | } | 117 | } |
112 | crypto_digest_init(crypt_stat->md5_tfm); | 118 | crypto_hash_init(&desc); |
113 | crypto_digest_update(crypt_stat->md5_tfm, &sg, 1); | 119 | crypto_hash_update(&desc, &sg, len); |
114 | crypto_digest_final(crypt_stat->md5_tfm, dst); | 120 | crypto_hash_final(&desc, dst); |
115 | mutex_unlock(&crypt_stat->cs_md5_tfm_mutex); | 121 | mutex_unlock(&crypt_stat->cs_hash_tfm_mutex); |
122 | out: | ||
123 | return rc; | ||
124 | } | ||
125 | |||
126 | int ecryptfs_crypto_api_algify_cipher_name(char **algified_name, | ||
127 | char *cipher_name, | ||
128 | char *chaining_modifier) | ||
129 | { | ||
130 | int cipher_name_len = strlen(cipher_name); | ||
131 | int chaining_modifier_len = strlen(chaining_modifier); | ||
132 | int algified_name_len; | ||
133 | int rc; | ||
134 | |||
135 | algified_name_len = (chaining_modifier_len + cipher_name_len + 3); | ||
136 | (*algified_name) = kmalloc(algified_name_len, GFP_KERNEL); | ||
137 | if (!(*algified_name)) { | ||
138 | rc = -ENOMEM; | ||
139 | goto out; | ||
140 | } | ||
141 | snprintf((*algified_name), algified_name_len, "%s(%s)", | ||
142 | chaining_modifier, cipher_name); | ||
143 | rc = 0; | ||
116 | out: | 144 | out: |
117 | return rc; | 145 | return rc; |
118 | } | 146 | } |
@@ -178,7 +206,7 @@ ecryptfs_init_crypt_stat(struct ecryptfs_crypt_stat *crypt_stat) | |||
178 | memset((void *)crypt_stat, 0, sizeof(struct ecryptfs_crypt_stat)); | 206 | memset((void *)crypt_stat, 0, sizeof(struct ecryptfs_crypt_stat)); |
179 | mutex_init(&crypt_stat->cs_mutex); | 207 | mutex_init(&crypt_stat->cs_mutex); |
180 | mutex_init(&crypt_stat->cs_tfm_mutex); | 208 | mutex_init(&crypt_stat->cs_tfm_mutex); |
181 | mutex_init(&crypt_stat->cs_md5_tfm_mutex); | 209 | mutex_init(&crypt_stat->cs_hash_tfm_mutex); |
182 | ECRYPTFS_SET_FLAG(crypt_stat->flags, ECRYPTFS_STRUCT_INITIALIZED); | 210 | ECRYPTFS_SET_FLAG(crypt_stat->flags, ECRYPTFS_STRUCT_INITIALIZED); |
183 | } | 211 | } |
184 | 212 | ||
@@ -191,9 +219,9 @@ ecryptfs_init_crypt_stat(struct ecryptfs_crypt_stat *crypt_stat) | |||
191 | void ecryptfs_destruct_crypt_stat(struct ecryptfs_crypt_stat *crypt_stat) | 219 | void ecryptfs_destruct_crypt_stat(struct ecryptfs_crypt_stat *crypt_stat) |
192 | { | 220 | { |
193 | if (crypt_stat->tfm) | 221 | if (crypt_stat->tfm) |
194 | crypto_free_tfm(crypt_stat->tfm); | 222 | crypto_free_blkcipher(crypt_stat->tfm); |
195 | if (crypt_stat->md5_tfm) | 223 | if (crypt_stat->hash_tfm) |
196 | crypto_free_tfm(crypt_stat->md5_tfm); | 224 | crypto_free_hash(crypt_stat->hash_tfm); |
197 | memset(crypt_stat, 0, sizeof(struct ecryptfs_crypt_stat)); | 225 | memset(crypt_stat, 0, sizeof(struct ecryptfs_crypt_stat)); |
198 | } | 226 | } |
199 | 227 | ||
@@ -203,7 +231,7 @@ void ecryptfs_destruct_mount_crypt_stat( | |||
203 | if (mount_crypt_stat->global_auth_tok_key) | 231 | if (mount_crypt_stat->global_auth_tok_key) |
204 | key_put(mount_crypt_stat->global_auth_tok_key); | 232 | key_put(mount_crypt_stat->global_auth_tok_key); |
205 | if (mount_crypt_stat->global_key_tfm) | 233 | if (mount_crypt_stat->global_key_tfm) |
206 | crypto_free_tfm(mount_crypt_stat->global_key_tfm); | 234 | crypto_free_blkcipher(mount_crypt_stat->global_key_tfm); |
207 | memset(mount_crypt_stat, 0, sizeof(struct ecryptfs_mount_crypt_stat)); | 235 | memset(mount_crypt_stat, 0, sizeof(struct ecryptfs_mount_crypt_stat)); |
208 | } | 236 | } |
209 | 237 | ||
@@ -269,6 +297,11 @@ static int encrypt_scatterlist(struct ecryptfs_crypt_stat *crypt_stat, | |||
269 | struct scatterlist *src_sg, int size, | 297 | struct scatterlist *src_sg, int size, |
270 | unsigned char *iv) | 298 | unsigned char *iv) |
271 | { | 299 | { |
300 | struct blkcipher_desc desc = { | ||
301 | .tfm = crypt_stat->tfm, | ||
302 | .info = iv, | ||
303 | .flags = CRYPTO_TFM_REQ_MAY_SLEEP | ||
304 | }; | ||
272 | int rc = 0; | 305 | int rc = 0; |
273 | 306 | ||
274 | BUG_ON(!crypt_stat || !crypt_stat->tfm | 307 | BUG_ON(!crypt_stat || !crypt_stat->tfm |
@@ -282,8 +315,8 @@ static int encrypt_scatterlist(struct ecryptfs_crypt_stat *crypt_stat, | |||
282 | } | 315 | } |
283 | /* Consider doing this once, when the file is opened */ | 316 | /* Consider doing this once, when the file is opened */ |
284 | mutex_lock(&crypt_stat->cs_tfm_mutex); | 317 | mutex_lock(&crypt_stat->cs_tfm_mutex); |
285 | rc = crypto_cipher_setkey(crypt_stat->tfm, crypt_stat->key, | 318 | rc = crypto_blkcipher_setkey(crypt_stat->tfm, crypt_stat->key, |
286 | crypt_stat->key_size); | 319 | crypt_stat->key_size); |
287 | if (rc) { | 320 | if (rc) { |
288 | ecryptfs_printk(KERN_ERR, "Error setting key; rc = [%d]\n", | 321 | ecryptfs_printk(KERN_ERR, "Error setting key; rc = [%d]\n", |
289 | rc); | 322 | rc); |
@@ -292,7 +325,7 @@ static int encrypt_scatterlist(struct ecryptfs_crypt_stat *crypt_stat, | |||
292 | goto out; | 325 | goto out; |
293 | } | 326 | } |
294 | ecryptfs_printk(KERN_DEBUG, "Encrypting [%d] bytes.\n", size); | 327 | ecryptfs_printk(KERN_DEBUG, "Encrypting [%d] bytes.\n", size); |
295 | crypto_cipher_encrypt_iv(crypt_stat->tfm, dest_sg, src_sg, size, iv); | 328 | crypto_blkcipher_encrypt_iv(&desc, dest_sg, src_sg, size); |
296 | mutex_unlock(&crypt_stat->cs_tfm_mutex); | 329 | mutex_unlock(&crypt_stat->cs_tfm_mutex); |
297 | out: | 330 | out: |
298 | return rc; | 331 | return rc; |
@@ -675,12 +708,17 @@ static int decrypt_scatterlist(struct ecryptfs_crypt_stat *crypt_stat, | |||
675 | struct scatterlist *src_sg, int size, | 708 | struct scatterlist *src_sg, int size, |
676 | unsigned char *iv) | 709 | unsigned char *iv) |
677 | { | 710 | { |
711 | struct blkcipher_desc desc = { | ||
712 | .tfm = crypt_stat->tfm, | ||
713 | .info = iv, | ||
714 | .flags = CRYPTO_TFM_REQ_MAY_SLEEP | ||
715 | }; | ||
678 | int rc = 0; | 716 | int rc = 0; |
679 | 717 | ||
680 | /* Consider doing this once, when the file is opened */ | 718 | /* Consider doing this once, when the file is opened */ |
681 | mutex_lock(&crypt_stat->cs_tfm_mutex); | 719 | mutex_lock(&crypt_stat->cs_tfm_mutex); |
682 | rc = crypto_cipher_setkey(crypt_stat->tfm, crypt_stat->key, | 720 | rc = crypto_blkcipher_setkey(crypt_stat->tfm, crypt_stat->key, |
683 | crypt_stat->key_size); | 721 | crypt_stat->key_size); |
684 | if (rc) { | 722 | if (rc) { |
685 | ecryptfs_printk(KERN_ERR, "Error setting key; rc = [%d]\n", | 723 | ecryptfs_printk(KERN_ERR, "Error setting key; rc = [%d]\n", |
686 | rc); | 724 | rc); |
@@ -689,8 +727,7 @@ static int decrypt_scatterlist(struct ecryptfs_crypt_stat *crypt_stat, | |||
689 | goto out; | 727 | goto out; |
690 | } | 728 | } |
691 | ecryptfs_printk(KERN_DEBUG, "Decrypting [%d] bytes.\n", size); | 729 | ecryptfs_printk(KERN_DEBUG, "Decrypting [%d] bytes.\n", size); |
692 | rc = crypto_cipher_decrypt_iv(crypt_stat->tfm, dest_sg, src_sg, size, | 730 | rc = crypto_blkcipher_decrypt_iv(&desc, dest_sg, src_sg, size); |
693 | iv); | ||
694 | mutex_unlock(&crypt_stat->cs_tfm_mutex); | 731 | mutex_unlock(&crypt_stat->cs_tfm_mutex); |
695 | if (rc) { | 732 | if (rc) { |
696 | ecryptfs_printk(KERN_ERR, "Error decrypting; rc = [%d]\n", | 733 | ecryptfs_printk(KERN_ERR, "Error decrypting; rc = [%d]\n", |
@@ -759,6 +796,7 @@ ecryptfs_decrypt_page_offset(struct ecryptfs_crypt_stat *crypt_stat, | |||
759 | */ | 796 | */ |
760 | int ecryptfs_init_crypt_ctx(struct ecryptfs_crypt_stat *crypt_stat) | 797 | int ecryptfs_init_crypt_ctx(struct ecryptfs_crypt_stat *crypt_stat) |
761 | { | 798 | { |
799 | char *full_alg_name; | ||
762 | int rc = -EINVAL; | 800 | int rc = -EINVAL; |
763 | 801 | ||
764 | if (!crypt_stat->cipher) { | 802 | if (!crypt_stat->cipher) { |
@@ -775,16 +813,25 @@ int ecryptfs_init_crypt_ctx(struct ecryptfs_crypt_stat *crypt_stat) | |||
775 | goto out; | 813 | goto out; |
776 | } | 814 | } |
777 | mutex_lock(&crypt_stat->cs_tfm_mutex); | 815 | mutex_lock(&crypt_stat->cs_tfm_mutex); |
778 | crypt_stat->tfm = crypto_alloc_tfm(crypt_stat->cipher, | 816 | rc = ecryptfs_crypto_api_algify_cipher_name(&full_alg_name, |
779 | ECRYPTFS_DEFAULT_CHAINING_MODE | 817 | crypt_stat->cipher, "cbc"); |
780 | | CRYPTO_TFM_REQ_WEAK_KEY); | 818 | if (rc) |
781 | mutex_unlock(&crypt_stat->cs_tfm_mutex); | 819 | goto out; |
782 | if (!crypt_stat->tfm) { | 820 | crypt_stat->tfm = crypto_alloc_blkcipher(full_alg_name, 0, |
821 | CRYPTO_ALG_ASYNC); | ||
822 | kfree(full_alg_name); | ||
823 | if (IS_ERR(crypt_stat->tfm)) { | ||
824 | rc = PTR_ERR(crypt_stat->tfm); | ||
783 | ecryptfs_printk(KERN_ERR, "cryptfs: init_crypt_ctx(): " | 825 | ecryptfs_printk(KERN_ERR, "cryptfs: init_crypt_ctx(): " |
784 | "Error initializing cipher [%s]\n", | 826 | "Error initializing cipher [%s]\n", |
785 | crypt_stat->cipher); | 827 | crypt_stat->cipher); |
828 | mutex_unlock(&crypt_stat->cs_tfm_mutex); | ||
786 | goto out; | 829 | goto out; |
787 | } | 830 | } |
831 | crypto_blkcipher_set_flags(crypt_stat->tfm, | ||
832 | (ECRYPTFS_DEFAULT_CHAINING_MODE | ||
833 | | CRYPTO_TFM_REQ_WEAK_KEY)); | ||
834 | mutex_unlock(&crypt_stat->cs_tfm_mutex); | ||
788 | rc = 0; | 835 | rc = 0; |
789 | out: | 836 | out: |
790 | return rc; | 837 | return rc; |
@@ -1145,28 +1192,28 @@ int ecryptfs_cipher_code_to_string(char *str, u16 cipher_code) | |||
1145 | int ecryptfs_read_header_region(char *data, struct dentry *dentry, | 1192 | int ecryptfs_read_header_region(char *data, struct dentry *dentry, |
1146 | struct vfsmount *mnt) | 1193 | struct vfsmount *mnt) |
1147 | { | 1194 | { |
1148 | struct file *file; | 1195 | struct file *lower_file; |
1149 | mm_segment_t oldfs; | 1196 | mm_segment_t oldfs; |
1150 | int rc; | 1197 | int rc; |
1151 | 1198 | ||
1152 | mnt = mntget(mnt); | 1199 | if ((rc = ecryptfs_open_lower_file(&lower_file, dentry, mnt, |
1153 | file = dentry_open(dentry, mnt, O_RDONLY); | 1200 | O_RDONLY))) { |
1154 | if (IS_ERR(file)) { | 1201 | printk(KERN_ERR |
1155 | ecryptfs_printk(KERN_DEBUG, "Error opening file to " | 1202 | "Error opening lower_file to read header region\n"); |
1156 | "read header region\n"); | ||
1157 | mntput(mnt); | ||
1158 | rc = PTR_ERR(file); | ||
1159 | goto out; | 1203 | goto out; |
1160 | } | 1204 | } |
1161 | file->f_pos = 0; | 1205 | lower_file->f_pos = 0; |
1162 | oldfs = get_fs(); | 1206 | oldfs = get_fs(); |
1163 | set_fs(get_ds()); | 1207 | set_fs(get_ds()); |
1164 | /* For releases 0.1 and 0.2, all of the header information | 1208 | /* For releases 0.1 and 0.2, all of the header information |
1165 | * fits in the first data extent-sized region. */ | 1209 | * fits in the first data extent-sized region. */ |
1166 | rc = file->f_op->read(file, (char __user *)data, | 1210 | rc = lower_file->f_op->read(lower_file, (char __user *)data, |
1167 | ECRYPTFS_DEFAULT_EXTENT_SIZE, &file->f_pos); | 1211 | ECRYPTFS_DEFAULT_EXTENT_SIZE, &lower_file->f_pos); |
1168 | set_fs(oldfs); | 1212 | set_fs(oldfs); |
1169 | fput(file); | 1213 | if ((rc = ecryptfs_close_lower_file(lower_file))) { |
1214 | printk(KERN_ERR "Error closing lower_file\n"); | ||
1215 | goto out; | ||
1216 | } | ||
1170 | rc = 0; | 1217 | rc = 0; |
1171 | out: | 1218 | out: |
1172 | return rc; | 1219 | return rc; |
@@ -1573,84 +1620,52 @@ out: | |||
1573 | 1620 | ||
1574 | /** | 1621 | /** |
1575 | * ecryptfs_process_cipher - Perform cipher initialization. | 1622 | * ecryptfs_process_cipher - Perform cipher initialization. |
1576 | * @tfm: Crypto context set by this function | ||
1577 | * @key_tfm: Crypto context for key material, set by this function | 1623 | * @key_tfm: Crypto context for key material, set by this function |
1578 | * @cipher_name: Name of the cipher. | 1624 | * @cipher_name: Name of the cipher |
1579 | * @key_size: Size of the key in bytes. | 1625 | * @key_size: Size of the key in bytes |
1580 | * | 1626 | * |
1581 | * Returns zero on success. Any crypto_tfm structs allocated here | 1627 | * Returns zero on success. Any crypto_tfm structs allocated here |
1582 | * should be released by other functions, such as on a superblock put | 1628 | * should be released by other functions, such as on a superblock put |
1583 | * event, regardless of whether this function succeeds for fails. | 1629 | * event, regardless of whether this function succeeds for fails. |
1584 | */ | 1630 | */ |
1585 | int | 1631 | int |
1586 | ecryptfs_process_cipher(struct crypto_tfm **tfm, struct crypto_tfm **key_tfm, | 1632 | ecryptfs_process_cipher(struct crypto_blkcipher **key_tfm, char *cipher_name, |
1587 | char *cipher_name, size_t key_size) | 1633 | size_t *key_size) |
1588 | { | 1634 | { |
1589 | char dummy_key[ECRYPTFS_MAX_KEY_BYTES]; | 1635 | char dummy_key[ECRYPTFS_MAX_KEY_BYTES]; |
1636 | char *full_alg_name; | ||
1590 | int rc; | 1637 | int rc; |
1591 | 1638 | ||
1592 | *tfm = *key_tfm = NULL; | 1639 | *key_tfm = NULL; |
1593 | if (key_size > ECRYPTFS_MAX_KEY_BYTES) { | 1640 | if (*key_size > ECRYPTFS_MAX_KEY_BYTES) { |
1594 | rc = -EINVAL; | 1641 | rc = -EINVAL; |
1595 | printk(KERN_ERR "Requested key size is [%Zd] bytes; maximum " | 1642 | printk(KERN_ERR "Requested key size is [%Zd] bytes; maximum " |
1596 | "allowable is [%d]\n", key_size, ECRYPTFS_MAX_KEY_BYTES); | 1643 | "allowable is [%d]\n", *key_size, ECRYPTFS_MAX_KEY_BYTES); |
1597 | goto out; | 1644 | goto out; |
1598 | } | 1645 | } |
1599 | *tfm = crypto_alloc_tfm(cipher_name, (ECRYPTFS_DEFAULT_CHAINING_MODE | 1646 | rc = ecryptfs_crypto_api_algify_cipher_name(&full_alg_name, cipher_name, |
1600 | | CRYPTO_TFM_REQ_WEAK_KEY)); | 1647 | "ecb"); |
1601 | if (!(*tfm)) { | 1648 | if (rc) |
1602 | rc = -EINVAL; | ||
1603 | printk(KERN_ERR "Unable to allocate crypto cipher with name " | ||
1604 | "[%s]\n", cipher_name); | ||
1605 | goto out; | 1649 | goto out; |
1606 | } | 1650 | *key_tfm = crypto_alloc_blkcipher(full_alg_name, 0, CRYPTO_ALG_ASYNC); |
1607 | *key_tfm = crypto_alloc_tfm(cipher_name, CRYPTO_TFM_REQ_WEAK_KEY); | 1651 | kfree(full_alg_name); |
1608 | if (!(*key_tfm)) { | 1652 | if (IS_ERR(*key_tfm)) { |
1609 | rc = -EINVAL; | 1653 | rc = PTR_ERR(*key_tfm); |
1610 | printk(KERN_ERR "Unable to allocate crypto cipher with name " | 1654 | printk(KERN_ERR "Unable to allocate crypto cipher with name " |
1611 | "[%s]\n", cipher_name); | 1655 | "[%s]; rc = [%d]\n", cipher_name, rc); |
1612 | goto out; | ||
1613 | } | ||
1614 | if (key_size < crypto_tfm_alg_min_keysize(*tfm)) { | ||
1615 | rc = -EINVAL; | ||
1616 | printk(KERN_ERR "Request key size is [%Zd]; minimum key size " | ||
1617 | "supported by cipher [%s] is [%d]\n", key_size, | ||
1618 | cipher_name, crypto_tfm_alg_min_keysize(*tfm)); | ||
1619 | goto out; | ||
1620 | } | ||
1621 | if (key_size < crypto_tfm_alg_min_keysize(*key_tfm)) { | ||
1622 | rc = -EINVAL; | ||
1623 | printk(KERN_ERR "Request key size is [%Zd]; minimum key size " | ||
1624 | "supported by cipher [%s] is [%d]\n", key_size, | ||
1625 | cipher_name, crypto_tfm_alg_min_keysize(*key_tfm)); | ||
1626 | goto out; | 1656 | goto out; |
1627 | } | 1657 | } |
1628 | if (key_size > crypto_tfm_alg_max_keysize(*tfm)) { | 1658 | crypto_blkcipher_set_flags(*key_tfm, CRYPTO_TFM_REQ_WEAK_KEY); |
1629 | rc = -EINVAL; | 1659 | if (*key_size == 0) { |
1630 | printk(KERN_ERR "Request key size is [%Zd]; maximum key size " | 1660 | struct blkcipher_alg *alg = crypto_blkcipher_alg(*key_tfm); |
1631 | "supported by cipher [%s] is [%d]\n", key_size, | 1661 | |
1632 | cipher_name, crypto_tfm_alg_min_keysize(*tfm)); | 1662 | *key_size = alg->max_keysize; |
1633 | goto out; | ||
1634 | } | ||
1635 | if (key_size > crypto_tfm_alg_max_keysize(*key_tfm)) { | ||
1636 | rc = -EINVAL; | ||
1637 | printk(KERN_ERR "Request key size is [%Zd]; maximum key size " | ||
1638 | "supported by cipher [%s] is [%d]\n", key_size, | ||
1639 | cipher_name, crypto_tfm_alg_min_keysize(*key_tfm)); | ||
1640 | goto out; | ||
1641 | } | ||
1642 | get_random_bytes(dummy_key, key_size); | ||
1643 | rc = crypto_cipher_setkey(*tfm, dummy_key, key_size); | ||
1644 | if (rc) { | ||
1645 | printk(KERN_ERR "Error attempting to set key of size [%Zd] for " | ||
1646 | "cipher [%s]; rc = [%d]\n", key_size, cipher_name, rc); | ||
1647 | rc = -EINVAL; | ||
1648 | goto out; | ||
1649 | } | 1663 | } |
1650 | rc = crypto_cipher_setkey(*key_tfm, dummy_key, key_size); | 1664 | get_random_bytes(dummy_key, *key_size); |
1665 | rc = crypto_blkcipher_setkey(*key_tfm, dummy_key, *key_size); | ||
1651 | if (rc) { | 1666 | if (rc) { |
1652 | printk(KERN_ERR "Error attempting to set key of size [%Zd] for " | 1667 | printk(KERN_ERR "Error attempting to set key of size [%Zd] for " |
1653 | "cipher [%s]; rc = [%d]\n", key_size, cipher_name, rc); | 1668 | "cipher [%s]; rc = [%d]\n", *key_size, cipher_name, rc); |
1654 | rc = -EINVAL; | 1669 | rc = -EINVAL; |
1655 | goto out; | 1670 | goto out; |
1656 | } | 1671 | } |
diff --git a/fs/ecryptfs/dentry.c b/fs/ecryptfs/dentry.c index f0d2a433242b..52d1e36dc746 100644 --- a/fs/ecryptfs/dentry.c +++ b/fs/ecryptfs/dentry.c | |||
@@ -24,6 +24,7 @@ | |||
24 | 24 | ||
25 | #include <linux/dcache.h> | 25 | #include <linux/dcache.h> |
26 | #include <linux/namei.h> | 26 | #include <linux/namei.h> |
27 | #include <linux/mount.h> | ||
27 | #include "ecryptfs_kernel.h" | 28 | #include "ecryptfs_kernel.h" |
28 | 29 | ||
29 | /** | 30 | /** |
@@ -56,6 +57,12 @@ static int ecryptfs_d_revalidate(struct dentry *dentry, struct nameidata *nd) | |||
56 | rc = lower_dentry->d_op->d_revalidate(lower_dentry, nd); | 57 | rc = lower_dentry->d_op->d_revalidate(lower_dentry, nd); |
57 | nd->dentry = dentry_save; | 58 | nd->dentry = dentry_save; |
58 | nd->mnt = vfsmount_save; | 59 | nd->mnt = vfsmount_save; |
60 | if (dentry->d_inode) { | ||
61 | struct inode *lower_inode = | ||
62 | ecryptfs_inode_to_lower(dentry->d_inode); | ||
63 | |||
64 | ecryptfs_copy_attr_all(dentry->d_inode, lower_inode); | ||
65 | } | ||
59 | out: | 66 | out: |
60 | return rc; | 67 | return rc; |
61 | } | 68 | } |
@@ -76,8 +83,13 @@ static void ecryptfs_d_release(struct dentry *dentry) | |||
76 | if (ecryptfs_dentry_to_private(dentry)) | 83 | if (ecryptfs_dentry_to_private(dentry)) |
77 | kmem_cache_free(ecryptfs_dentry_info_cache, | 84 | kmem_cache_free(ecryptfs_dentry_info_cache, |
78 | ecryptfs_dentry_to_private(dentry)); | 85 | ecryptfs_dentry_to_private(dentry)); |
79 | if (lower_dentry) | 86 | if (lower_dentry) { |
87 | struct vfsmount *lower_mnt = | ||
88 | ecryptfs_dentry_to_lower_mnt(dentry); | ||
89 | |||
90 | mntput(lower_mnt); | ||
80 | dput(lower_dentry); | 91 | dput(lower_dentry); |
92 | } | ||
81 | return; | 93 | return; |
82 | } | 94 | } |
83 | 95 | ||
diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h index 872c9958531a..f992533d1692 100644 --- a/fs/ecryptfs/ecryptfs_kernel.h +++ b/fs/ecryptfs/ecryptfs_kernel.h | |||
@@ -175,6 +175,7 @@ ecryptfs_get_key_payload_data(struct key *key) | |||
175 | #define ECRYPTFS_DEFAULT_CIPHER "aes" | 175 | #define ECRYPTFS_DEFAULT_CIPHER "aes" |
176 | #define ECRYPTFS_DEFAULT_KEY_BYTES 16 | 176 | #define ECRYPTFS_DEFAULT_KEY_BYTES 16 |
177 | #define ECRYPTFS_DEFAULT_CHAINING_MODE CRYPTO_TFM_MODE_CBC | 177 | #define ECRYPTFS_DEFAULT_CHAINING_MODE CRYPTO_TFM_MODE_CBC |
178 | #define ECRYPTFS_DEFAULT_HASH "md5" | ||
178 | #define ECRYPTFS_TAG_3_PACKET_TYPE 0x8C | 179 | #define ECRYPTFS_TAG_3_PACKET_TYPE 0x8C |
179 | #define ECRYPTFS_TAG_11_PACKET_TYPE 0xED | 180 | #define ECRYPTFS_TAG_11_PACKET_TYPE 0xED |
180 | #define MD5_DIGEST_SIZE 16 | 181 | #define MD5_DIGEST_SIZE 16 |
@@ -204,15 +205,15 @@ struct ecryptfs_crypt_stat { | |||
204 | size_t extent_shift; | 205 | size_t extent_shift; |
205 | unsigned int extent_mask; | 206 | unsigned int extent_mask; |
206 | struct ecryptfs_mount_crypt_stat *mount_crypt_stat; | 207 | struct ecryptfs_mount_crypt_stat *mount_crypt_stat; |
207 | struct crypto_tfm *tfm; | 208 | struct crypto_blkcipher *tfm; |
208 | struct crypto_tfm *md5_tfm; /* Crypto context for generating | 209 | struct crypto_hash *hash_tfm; /* Crypto context for generating |
209 | * the initialization vectors */ | 210 | * the initialization vectors */ |
210 | unsigned char cipher[ECRYPTFS_MAX_CIPHER_NAME_SIZE]; | 211 | unsigned char cipher[ECRYPTFS_MAX_CIPHER_NAME_SIZE]; |
211 | unsigned char key[ECRYPTFS_MAX_KEY_BYTES]; | 212 | unsigned char key[ECRYPTFS_MAX_KEY_BYTES]; |
212 | unsigned char root_iv[ECRYPTFS_MAX_IV_BYTES]; | 213 | unsigned char root_iv[ECRYPTFS_MAX_IV_BYTES]; |
213 | unsigned char keysigs[ECRYPTFS_MAX_NUM_KEYSIGS][ECRYPTFS_SIG_SIZE_HEX]; | 214 | unsigned char keysigs[ECRYPTFS_MAX_NUM_KEYSIGS][ECRYPTFS_SIG_SIZE_HEX]; |
214 | struct mutex cs_tfm_mutex; | 215 | struct mutex cs_tfm_mutex; |
215 | struct mutex cs_md5_tfm_mutex; | 216 | struct mutex cs_hash_tfm_mutex; |
216 | struct mutex cs_mutex; | 217 | struct mutex cs_mutex; |
217 | }; | 218 | }; |
218 | 219 | ||
@@ -244,7 +245,7 @@ struct ecryptfs_mount_crypt_stat { | |||
244 | struct ecryptfs_auth_tok *global_auth_tok; | 245 | struct ecryptfs_auth_tok *global_auth_tok; |
245 | struct key *global_auth_tok_key; | 246 | struct key *global_auth_tok_key; |
246 | size_t global_default_cipher_key_size; | 247 | size_t global_default_cipher_key_size; |
247 | struct crypto_tfm *global_key_tfm; | 248 | struct crypto_blkcipher *global_key_tfm; |
248 | struct mutex global_key_tfm_mutex; | 249 | struct mutex global_key_tfm_mutex; |
249 | unsigned char global_default_cipher_name[ECRYPTFS_MAX_CIPHER_NAME_SIZE | 250 | unsigned char global_default_cipher_name[ECRYPTFS_MAX_CIPHER_NAME_SIZE |
250 | + 1]; | 251 | + 1]; |
@@ -425,6 +426,9 @@ void ecryptfs_destruct_crypt_stat(struct ecryptfs_crypt_stat *crypt_stat); | |||
425 | void ecryptfs_destruct_mount_crypt_stat( | 426 | void ecryptfs_destruct_mount_crypt_stat( |
426 | struct ecryptfs_mount_crypt_stat *mount_crypt_stat); | 427 | struct ecryptfs_mount_crypt_stat *mount_crypt_stat); |
427 | int ecryptfs_init_crypt_ctx(struct ecryptfs_crypt_stat *crypt_stat); | 428 | int ecryptfs_init_crypt_ctx(struct ecryptfs_crypt_stat *crypt_stat); |
429 | int ecryptfs_crypto_api_algify_cipher_name(char **algified_name, | ||
430 | char *cipher_name, | ||
431 | char *chaining_modifier); | ||
428 | int ecryptfs_write_inode_size_to_header(struct file *lower_file, | 432 | int ecryptfs_write_inode_size_to_header(struct file *lower_file, |
429 | struct inode *lower_inode, | 433 | struct inode *lower_inode, |
430 | struct inode *inode); | 434 | struct inode *inode); |
@@ -473,10 +477,14 @@ ecryptfs_parse_packet_set(struct ecryptfs_crypt_stat *crypt_stat, | |||
473 | unsigned char *src, struct dentry *ecryptfs_dentry); | 477 | unsigned char *src, struct dentry *ecryptfs_dentry); |
474 | int ecryptfs_truncate(struct dentry *dentry, loff_t new_length); | 478 | int ecryptfs_truncate(struct dentry *dentry, loff_t new_length); |
475 | int | 479 | int |
476 | ecryptfs_process_cipher(struct crypto_tfm **tfm, struct crypto_tfm **key_tfm, | 480 | ecryptfs_process_cipher(struct crypto_blkcipher **key_tfm, char *cipher_name, |
477 | char *cipher_name, size_t key_size); | 481 | size_t *key_size); |
478 | int ecryptfs_inode_test(struct inode *inode, void *candidate_lower_inode); | 482 | int ecryptfs_inode_test(struct inode *inode, void *candidate_lower_inode); |
479 | int ecryptfs_inode_set(struct inode *inode, void *lower_inode); | 483 | int ecryptfs_inode_set(struct inode *inode, void *lower_inode); |
480 | void ecryptfs_init_inode(struct inode *inode, struct inode *lower_inode); | 484 | void ecryptfs_init_inode(struct inode *inode, struct inode *lower_inode); |
485 | int ecryptfs_open_lower_file(struct file **lower_file, | ||
486 | struct dentry *lower_dentry, | ||
487 | struct vfsmount *lower_mnt, int flags); | ||
488 | int ecryptfs_close_lower_file(struct file *lower_file); | ||
481 | 489 | ||
482 | #endif /* #ifndef ECRYPTFS_KERNEL_H */ | 490 | #endif /* #ifndef ECRYPTFS_KERNEL_H */ |
diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c index c8550c9f9cd2..a92ef05eff8f 100644 --- a/fs/ecryptfs/file.c +++ b/fs/ecryptfs/file.c | |||
@@ -198,6 +198,33 @@ retry: | |||
198 | 198 | ||
199 | struct kmem_cache *ecryptfs_file_info_cache; | 199 | struct kmem_cache *ecryptfs_file_info_cache; |
200 | 200 | ||
201 | int ecryptfs_open_lower_file(struct file **lower_file, | ||
202 | struct dentry *lower_dentry, | ||
203 | struct vfsmount *lower_mnt, int flags) | ||
204 | { | ||
205 | int rc = 0; | ||
206 | |||
207 | dget(lower_dentry); | ||
208 | mntget(lower_mnt); | ||
209 | *lower_file = dentry_open(lower_dentry, lower_mnt, flags); | ||
210 | if (IS_ERR(*lower_file)) { | ||
211 | printk(KERN_ERR "Error opening lower file for lower_dentry " | ||
212 | "[0x%p], lower_mnt [0x%p], and flags [0x%x]\n", | ||
213 | lower_dentry, lower_mnt, flags); | ||
214 | rc = PTR_ERR(*lower_file); | ||
215 | *lower_file = NULL; | ||
216 | goto out; | ||
217 | } | ||
218 | out: | ||
219 | return rc; | ||
220 | } | ||
221 | |||
222 | int ecryptfs_close_lower_file(struct file *lower_file) | ||
223 | { | ||
224 | fput(lower_file); | ||
225 | return 0; | ||
226 | } | ||
227 | |||
201 | /** | 228 | /** |
202 | * ecryptfs_open | 229 | * ecryptfs_open |
203 | * @inode: inode speciying file to open | 230 | * @inode: inode speciying file to open |
@@ -244,19 +271,15 @@ static int ecryptfs_open(struct inode *inode, struct file *file) | |||
244 | ECRYPTFS_SET_FLAG(crypt_stat->flags, ECRYPTFS_ENCRYPTED); | 271 | ECRYPTFS_SET_FLAG(crypt_stat->flags, ECRYPTFS_ENCRYPTED); |
245 | } | 272 | } |
246 | mutex_unlock(&crypt_stat->cs_mutex); | 273 | mutex_unlock(&crypt_stat->cs_mutex); |
247 | /* This mntget & dget is undone via fput when the file is released */ | ||
248 | dget(lower_dentry); | ||
249 | lower_flags = file->f_flags; | 274 | lower_flags = file->f_flags; |
250 | if ((lower_flags & O_ACCMODE) == O_WRONLY) | 275 | if ((lower_flags & O_ACCMODE) == O_WRONLY) |
251 | lower_flags = (lower_flags & O_ACCMODE) | O_RDWR; | 276 | lower_flags = (lower_flags & O_ACCMODE) | O_RDWR; |
252 | if (file->f_flags & O_APPEND) | 277 | if (file->f_flags & O_APPEND) |
253 | lower_flags &= ~O_APPEND; | 278 | lower_flags &= ~O_APPEND; |
254 | lower_mnt = ecryptfs_dentry_to_lower_mnt(ecryptfs_dentry); | 279 | lower_mnt = ecryptfs_dentry_to_lower_mnt(ecryptfs_dentry); |
255 | mntget(lower_mnt); | ||
256 | /* Corresponding fput() in ecryptfs_release() */ | 280 | /* Corresponding fput() in ecryptfs_release() */ |
257 | lower_file = dentry_open(lower_dentry, lower_mnt, lower_flags); | 281 | if ((rc = ecryptfs_open_lower_file(&lower_file, lower_dentry, lower_mnt, |
258 | if (IS_ERR(lower_file)) { | 282 | lower_flags))) { |
259 | rc = PTR_ERR(lower_file); | ||
260 | ecryptfs_printk(KERN_ERR, "Error opening lower file\n"); | 283 | ecryptfs_printk(KERN_ERR, "Error opening lower file\n"); |
261 | goto out_puts; | 284 | goto out_puts; |
262 | } | 285 | } |
@@ -341,11 +364,16 @@ static int ecryptfs_release(struct inode *inode, struct file *file) | |||
341 | struct file *lower_file = ecryptfs_file_to_lower(file); | 364 | struct file *lower_file = ecryptfs_file_to_lower(file); |
342 | struct ecryptfs_file_info *file_info = ecryptfs_file_to_private(file); | 365 | struct ecryptfs_file_info *file_info = ecryptfs_file_to_private(file); |
343 | struct inode *lower_inode = ecryptfs_inode_to_lower(inode); | 366 | struct inode *lower_inode = ecryptfs_inode_to_lower(inode); |
367 | int rc; | ||
344 | 368 | ||
345 | fput(lower_file); | 369 | if ((rc = ecryptfs_close_lower_file(lower_file))) { |
370 | printk(KERN_ERR "Error closing lower_file\n"); | ||
371 | goto out; | ||
372 | } | ||
346 | inode->i_blocks = lower_inode->i_blocks; | 373 | inode->i_blocks = lower_inode->i_blocks; |
347 | kmem_cache_free(ecryptfs_file_info_cache, file_info); | 374 | kmem_cache_free(ecryptfs_file_info_cache, file_info); |
348 | return 0; | 375 | out: |
376 | return rc; | ||
349 | } | 377 | } |
350 | 378 | ||
351 | static int | 379 | static int |
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index efdd2b7b62d7..dfcc68484f47 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c | |||
@@ -231,7 +231,6 @@ static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry) | |||
231 | int lower_flags; | 231 | int lower_flags; |
232 | struct ecryptfs_crypt_stat *crypt_stat; | 232 | struct ecryptfs_crypt_stat *crypt_stat; |
233 | struct dentry *lower_dentry; | 233 | struct dentry *lower_dentry; |
234 | struct dentry *tlower_dentry = NULL; | ||
235 | struct file *lower_file; | 234 | struct file *lower_file; |
236 | struct inode *inode, *lower_inode; | 235 | struct inode *inode, *lower_inode; |
237 | struct vfsmount *lower_mnt; | 236 | struct vfsmount *lower_mnt; |
@@ -241,30 +240,19 @@ static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry) | |||
241 | lower_dentry->d_name.name); | 240 | lower_dentry->d_name.name); |
242 | inode = ecryptfs_dentry->d_inode; | 241 | inode = ecryptfs_dentry->d_inode; |
243 | crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat; | 242 | crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat; |
244 | tlower_dentry = dget(lower_dentry); | ||
245 | if (!tlower_dentry) { | ||
246 | rc = -ENOMEM; | ||
247 | ecryptfs_printk(KERN_ERR, "Error dget'ing lower_dentry\n"); | ||
248 | goto out; | ||
249 | } | ||
250 | lower_flags = ((O_CREAT | O_WRONLY | O_TRUNC) & O_ACCMODE) | O_RDWR; | 243 | lower_flags = ((O_CREAT | O_WRONLY | O_TRUNC) & O_ACCMODE) | O_RDWR; |
251 | #if BITS_PER_LONG != 32 | 244 | #if BITS_PER_LONG != 32 |
252 | lower_flags |= O_LARGEFILE; | 245 | lower_flags |= O_LARGEFILE; |
253 | #endif | 246 | #endif |
254 | lower_mnt = ecryptfs_dentry_to_lower_mnt(ecryptfs_dentry); | 247 | lower_mnt = ecryptfs_dentry_to_lower_mnt(ecryptfs_dentry); |
255 | mntget(lower_mnt); | ||
256 | /* Corresponding fput() at end of this function */ | 248 | /* Corresponding fput() at end of this function */ |
257 | lower_file = dentry_open(tlower_dentry, lower_mnt, lower_flags); | 249 | if ((rc = ecryptfs_open_lower_file(&lower_file, lower_dentry, lower_mnt, |
258 | if (IS_ERR(lower_file)) { | 250 | lower_flags))) { |
259 | rc = PTR_ERR(lower_file); | ||
260 | ecryptfs_printk(KERN_ERR, | 251 | ecryptfs_printk(KERN_ERR, |
261 | "Error opening dentry; rc = [%i]\n", rc); | 252 | "Error opening dentry; rc = [%i]\n", rc); |
262 | goto out; | 253 | goto out; |
263 | } | 254 | } |
264 | /* fput(lower_file) should handle the puts if we do this */ | 255 | lower_inode = lower_dentry->d_inode; |
265 | lower_file->f_dentry = tlower_dentry; | ||
266 | lower_file->f_vfsmnt = lower_mnt; | ||
267 | lower_inode = tlower_dentry->d_inode; | ||
268 | if (S_ISDIR(ecryptfs_dentry->d_inode->i_mode)) { | 256 | if (S_ISDIR(ecryptfs_dentry->d_inode->i_mode)) { |
269 | ecryptfs_printk(KERN_DEBUG, "This is a directory\n"); | 257 | ecryptfs_printk(KERN_DEBUG, "This is a directory\n"); |
270 | ECRYPTFS_CLEAR_FLAG(crypt_stat->flags, ECRYPTFS_ENCRYPTED); | 258 | ECRYPTFS_CLEAR_FLAG(crypt_stat->flags, ECRYPTFS_ENCRYPTED); |
@@ -285,7 +273,8 @@ static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry) | |||
285 | } | 273 | } |
286 | rc = grow_file(ecryptfs_dentry, lower_file, inode, lower_inode); | 274 | rc = grow_file(ecryptfs_dentry, lower_file, inode, lower_inode); |
287 | out_fput: | 275 | out_fput: |
288 | fput(lower_file); | 276 | if ((rc = ecryptfs_close_lower_file(lower_file))) |
277 | printk(KERN_ERR "Error closing lower_file\n"); | ||
289 | out: | 278 | out: |
290 | return rc; | 279 | return rc; |
291 | } | 280 | } |
@@ -336,7 +325,6 @@ static struct dentry *ecryptfs_lookup(struct inode *dir, struct dentry *dentry, | |||
336 | struct dentry *lower_dir_dentry; | 325 | struct dentry *lower_dir_dentry; |
337 | struct dentry *lower_dentry; | 326 | struct dentry *lower_dentry; |
338 | struct vfsmount *lower_mnt; | 327 | struct vfsmount *lower_mnt; |
339 | struct dentry *tlower_dentry = NULL; | ||
340 | char *encoded_name; | 328 | char *encoded_name; |
341 | unsigned int encoded_namelen; | 329 | unsigned int encoded_namelen; |
342 | struct ecryptfs_crypt_stat *crypt_stat = NULL; | 330 | struct ecryptfs_crypt_stat *crypt_stat = NULL; |
@@ -347,27 +335,32 @@ static struct dentry *ecryptfs_lookup(struct inode *dir, struct dentry *dentry, | |||
347 | lower_dir_dentry = ecryptfs_dentry_to_lower(dentry->d_parent); | 335 | lower_dir_dentry = ecryptfs_dentry_to_lower(dentry->d_parent); |
348 | dentry->d_op = &ecryptfs_dops; | 336 | dentry->d_op = &ecryptfs_dops; |
349 | if ((dentry->d_name.len == 1 && !strcmp(dentry->d_name.name, ".")) | 337 | if ((dentry->d_name.len == 1 && !strcmp(dentry->d_name.name, ".")) |
350 | || (dentry->d_name.len == 2 && !strcmp(dentry->d_name.name, ".."))) | 338 | || (dentry->d_name.len == 2 |
351 | goto out_drop; | 339 | && !strcmp(dentry->d_name.name, ".."))) { |
340 | d_drop(dentry); | ||
341 | goto out; | ||
342 | } | ||
352 | encoded_namelen = ecryptfs_encode_filename(crypt_stat, | 343 | encoded_namelen = ecryptfs_encode_filename(crypt_stat, |
353 | dentry->d_name.name, | 344 | dentry->d_name.name, |
354 | dentry->d_name.len, | 345 | dentry->d_name.len, |
355 | &encoded_name); | 346 | &encoded_name); |
356 | if (encoded_namelen < 0) { | 347 | if (encoded_namelen < 0) { |
357 | rc = encoded_namelen; | 348 | rc = encoded_namelen; |
358 | goto out_drop; | 349 | d_drop(dentry); |
350 | goto out; | ||
359 | } | 351 | } |
360 | ecryptfs_printk(KERN_DEBUG, "encoded_name = [%s]; encoded_namelen " | 352 | ecryptfs_printk(KERN_DEBUG, "encoded_name = [%s]; encoded_namelen " |
361 | "= [%d]\n", encoded_name, encoded_namelen); | 353 | "= [%d]\n", encoded_name, encoded_namelen); |
362 | lower_dentry = lookup_one_len(encoded_name, lower_dir_dentry, | 354 | lower_dentry = lookup_one_len(encoded_name, lower_dir_dentry, |
363 | encoded_namelen - 1); | 355 | encoded_namelen - 1); |
364 | kfree(encoded_name); | 356 | kfree(encoded_name); |
365 | lower_mnt = mntget(ecryptfs_dentry_to_lower_mnt(dentry->d_parent)); | ||
366 | if (IS_ERR(lower_dentry)) { | 357 | if (IS_ERR(lower_dentry)) { |
367 | ecryptfs_printk(KERN_ERR, "ERR from lower_dentry\n"); | 358 | ecryptfs_printk(KERN_ERR, "ERR from lower_dentry\n"); |
368 | rc = PTR_ERR(lower_dentry); | 359 | rc = PTR_ERR(lower_dentry); |
369 | goto out_drop; | 360 | d_drop(dentry); |
361 | goto out; | ||
370 | } | 362 | } |
363 | lower_mnt = mntget(ecryptfs_dentry_to_lower_mnt(dentry->d_parent)); | ||
371 | ecryptfs_printk(KERN_DEBUG, "lower_dentry = [%p]; lower_dentry->" | 364 | ecryptfs_printk(KERN_DEBUG, "lower_dentry = [%p]; lower_dentry->" |
372 | "d_name.name = [%s]\n", lower_dentry, | 365 | "d_name.name = [%s]\n", lower_dentry, |
373 | lower_dentry->d_name.name); | 366 | lower_dentry->d_name.name); |
@@ -408,12 +401,6 @@ static struct dentry *ecryptfs_lookup(struct inode *dir, struct dentry *dentry, | |||
408 | "as we *think* we are about to unlink\n"); | 401 | "as we *think* we are about to unlink\n"); |
409 | goto out; | 402 | goto out; |
410 | } | 403 | } |
411 | tlower_dentry = dget(lower_dentry); | ||
412 | if (!tlower_dentry || IS_ERR(tlower_dentry)) { | ||
413 | rc = -ENOMEM; | ||
414 | ecryptfs_printk(KERN_ERR, "Cannot dget lower_dentry\n"); | ||
415 | goto out_dput; | ||
416 | } | ||
417 | /* Released in this function */ | 404 | /* Released in this function */ |
418 | page_virt = | 405 | page_virt = |
419 | (char *)kmem_cache_alloc(ecryptfs_header_cache_2, | 406 | (char *)kmem_cache_alloc(ecryptfs_header_cache_2, |
@@ -425,7 +412,7 @@ static struct dentry *ecryptfs_lookup(struct inode *dir, struct dentry *dentry, | |||
425 | goto out_dput; | 412 | goto out_dput; |
426 | } | 413 | } |
427 | memset(page_virt, 0, PAGE_CACHE_SIZE); | 414 | memset(page_virt, 0, PAGE_CACHE_SIZE); |
428 | rc = ecryptfs_read_header_region(page_virt, tlower_dentry, nd->mnt); | 415 | rc = ecryptfs_read_header_region(page_virt, lower_dentry, nd->mnt); |
429 | crypt_stat = &ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat; | 416 | crypt_stat = &ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat; |
430 | if (!ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_POLICY_APPLIED)) | 417 | if (!ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_POLICY_APPLIED)) |
431 | ecryptfs_set_default_sizes(crypt_stat); | 418 | ecryptfs_set_default_sizes(crypt_stat); |
@@ -448,9 +435,6 @@ static struct dentry *ecryptfs_lookup(struct inode *dir, struct dentry *dentry, | |||
448 | 435 | ||
449 | out_dput: | 436 | out_dput: |
450 | dput(lower_dentry); | 437 | dput(lower_dentry); |
451 | if (tlower_dentry) | ||
452 | dput(tlower_dentry); | ||
453 | out_drop: | ||
454 | d_drop(dentry); | 438 | d_drop(dentry); |
455 | out: | 439 | out: |
456 | return ERR_PTR(rc); | 440 | return ERR_PTR(rc); |
@@ -486,8 +470,9 @@ out_lock: | |||
486 | unlock_dir(lower_dir_dentry); | 470 | unlock_dir(lower_dir_dentry); |
487 | dput(lower_new_dentry); | 471 | dput(lower_new_dentry); |
488 | dput(lower_old_dentry); | 472 | dput(lower_old_dentry); |
489 | if (!new_dentry->d_inode) | 473 | d_drop(lower_old_dentry); |
490 | d_drop(new_dentry); | 474 | d_drop(new_dentry); |
475 | d_drop(old_dentry); | ||
491 | return rc; | 476 | return rc; |
492 | } | 477 | } |
493 | 478 | ||
@@ -500,7 +485,7 @@ static int ecryptfs_unlink(struct inode *dir, struct dentry *dentry) | |||
500 | lock_parent(lower_dentry); | 485 | lock_parent(lower_dentry); |
501 | rc = vfs_unlink(lower_dir_inode, lower_dentry); | 486 | rc = vfs_unlink(lower_dir_inode, lower_dentry); |
502 | if (rc) { | 487 | if (rc) { |
503 | ecryptfs_printk(KERN_ERR, "Error in vfs_unlink\n"); | 488 | printk(KERN_ERR "Error in vfs_unlink; rc = [%d]\n", rc); |
504 | goto out_unlock; | 489 | goto out_unlock; |
505 | } | 490 | } |
506 | ecryptfs_copy_attr_times(dir, lower_dir_inode); | 491 | ecryptfs_copy_attr_times(dir, lower_dir_inode); |
@@ -576,41 +561,24 @@ out: | |||
576 | 561 | ||
577 | static int ecryptfs_rmdir(struct inode *dir, struct dentry *dentry) | 562 | static int ecryptfs_rmdir(struct inode *dir, struct dentry *dentry) |
578 | { | 563 | { |
579 | int rc = 0; | ||
580 | struct dentry *tdentry = NULL; | ||
581 | struct dentry *lower_dentry; | 564 | struct dentry *lower_dentry; |
582 | struct dentry *tlower_dentry = NULL; | ||
583 | struct dentry *lower_dir_dentry; | 565 | struct dentry *lower_dir_dentry; |
566 | int rc; | ||
584 | 567 | ||
585 | lower_dentry = ecryptfs_dentry_to_lower(dentry); | 568 | lower_dentry = ecryptfs_dentry_to_lower(dentry); |
586 | if (!(tdentry = dget(dentry))) { | 569 | dget(dentry); |
587 | rc = -EINVAL; | ||
588 | ecryptfs_printk(KERN_ERR, "Error dget'ing dentry [%p]\n", | ||
589 | dentry); | ||
590 | goto out; | ||
591 | } | ||
592 | lower_dir_dentry = lock_parent(lower_dentry); | 570 | lower_dir_dentry = lock_parent(lower_dentry); |
593 | if (!(tlower_dentry = dget(lower_dentry))) { | 571 | dget(lower_dentry); |
594 | rc = -EINVAL; | ||
595 | ecryptfs_printk(KERN_ERR, "Error dget'ing lower_dentry " | ||
596 | "[%p]\n", lower_dentry); | ||
597 | goto out; | ||
598 | } | ||
599 | rc = vfs_rmdir(lower_dir_dentry->d_inode, lower_dentry); | 572 | rc = vfs_rmdir(lower_dir_dentry->d_inode, lower_dentry); |
600 | if (!rc) { | 573 | dput(lower_dentry); |
601 | d_delete(tlower_dentry); | 574 | if (!rc) |
602 | tlower_dentry = NULL; | 575 | d_delete(lower_dentry); |
603 | } | ||
604 | ecryptfs_copy_attr_times(dir, lower_dir_dentry->d_inode); | 576 | ecryptfs_copy_attr_times(dir, lower_dir_dentry->d_inode); |
605 | dir->i_nlink = lower_dir_dentry->d_inode->i_nlink; | 577 | dir->i_nlink = lower_dir_dentry->d_inode->i_nlink; |
606 | unlock_dir(lower_dir_dentry); | 578 | unlock_dir(lower_dir_dentry); |
607 | if (!rc) | 579 | if (!rc) |
608 | d_drop(dentry); | 580 | d_drop(dentry); |
609 | out: | 581 | dput(dentry); |
610 | if (tdentry) | ||
611 | dput(tdentry); | ||
612 | if (tlower_dentry) | ||
613 | dput(tlower_dentry); | ||
614 | return rc; | 582 | return rc; |
615 | } | 583 | } |
616 | 584 | ||
@@ -663,6 +631,8 @@ ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
663 | ecryptfs_copy_attr_all(old_dir, lower_old_dir_dentry->d_inode); | 631 | ecryptfs_copy_attr_all(old_dir, lower_old_dir_dentry->d_inode); |
664 | out_lock: | 632 | out_lock: |
665 | unlock_rename(lower_old_dir_dentry, lower_new_dir_dentry); | 633 | unlock_rename(lower_old_dir_dentry, lower_new_dir_dentry); |
634 | dput(lower_new_dentry->d_parent); | ||
635 | dput(lower_old_dentry->d_parent); | ||
666 | dput(lower_new_dentry); | 636 | dput(lower_new_dentry); |
667 | dput(lower_old_dentry); | 637 | dput(lower_old_dentry); |
668 | return rc; | 638 | return rc; |
@@ -832,12 +802,11 @@ int ecryptfs_truncate(struct dentry *dentry, loff_t new_length) | |||
832 | } | 802 | } |
833 | lower_dentry = ecryptfs_dentry_to_lower(dentry); | 803 | lower_dentry = ecryptfs_dentry_to_lower(dentry); |
834 | /* This dget & mntget is released through fput at out_fput: */ | 804 | /* This dget & mntget is released through fput at out_fput: */ |
835 | dget(lower_dentry); | ||
836 | lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry); | 805 | lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry); |
837 | mntget(lower_mnt); | 806 | if ((rc = ecryptfs_open_lower_file(&lower_file, lower_dentry, lower_mnt, |
838 | lower_file = dentry_open(lower_dentry, lower_mnt, O_RDWR); | 807 | O_RDWR))) { |
839 | if (unlikely(IS_ERR(lower_file))) { | 808 | ecryptfs_printk(KERN_ERR, |
840 | rc = PTR_ERR(lower_file); | 809 | "Error opening dentry; rc = [%i]\n", rc); |
841 | goto out_free; | 810 | goto out_free; |
842 | } | 811 | } |
843 | ecryptfs_set_file_lower(&fake_ecryptfs_file, lower_file); | 812 | ecryptfs_set_file_lower(&fake_ecryptfs_file, lower_file); |
@@ -879,7 +848,8 @@ int ecryptfs_truncate(struct dentry *dentry, loff_t new_length) | |||
879 | = CURRENT_TIME; | 848 | = CURRENT_TIME; |
880 | mark_inode_dirty_sync(inode); | 849 | mark_inode_dirty_sync(inode); |
881 | out_fput: | 850 | out_fput: |
882 | fput(lower_file); | 851 | if ((rc = ecryptfs_close_lower_file(lower_file))) |
852 | printk(KERN_ERR "Error closing lower_file\n"); | ||
883 | out_free: | 853 | out_free: |
884 | if (ecryptfs_file_to_private(&fake_ecryptfs_file)) | 854 | if (ecryptfs_file_to_private(&fake_ecryptfs_file)) |
885 | kmem_cache_free(ecryptfs_file_info_cache, | 855 | kmem_cache_free(ecryptfs_file_info_cache, |
diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c index ba454785a0c5..c3746f56d162 100644 --- a/fs/ecryptfs/keystore.c +++ b/fs/ecryptfs/keystore.c | |||
@@ -458,14 +458,16 @@ out: | |||
458 | static int decrypt_session_key(struct ecryptfs_auth_tok *auth_tok, | 458 | static int decrypt_session_key(struct ecryptfs_auth_tok *auth_tok, |
459 | struct ecryptfs_crypt_stat *crypt_stat) | 459 | struct ecryptfs_crypt_stat *crypt_stat) |
460 | { | 460 | { |
461 | int rc = 0; | ||
462 | struct ecryptfs_password *password_s_ptr; | 461 | struct ecryptfs_password *password_s_ptr; |
463 | struct crypto_tfm *tfm = NULL; | ||
464 | struct scatterlist src_sg[2], dst_sg[2]; | 462 | struct scatterlist src_sg[2], dst_sg[2]; |
465 | struct mutex *tfm_mutex = NULL; | 463 | struct mutex *tfm_mutex = NULL; |
466 | /* TODO: Use virt_to_scatterlist for these */ | 464 | /* TODO: Use virt_to_scatterlist for these */ |
467 | char *encrypted_session_key; | 465 | char *encrypted_session_key; |
468 | char *session_key; | 466 | char *session_key; |
467 | struct blkcipher_desc desc = { | ||
468 | .flags = CRYPTO_TFM_REQ_MAY_SLEEP | ||
469 | }; | ||
470 | int rc = 0; | ||
469 | 471 | ||
470 | password_s_ptr = &auth_tok->token.password; | 472 | password_s_ptr = &auth_tok->token.password; |
471 | if (ECRYPTFS_CHECK_FLAG(password_s_ptr->flags, | 473 | if (ECRYPTFS_CHECK_FLAG(password_s_ptr->flags, |
@@ -482,30 +484,37 @@ static int decrypt_session_key(struct ecryptfs_auth_tok *auth_tok, | |||
482 | if (!strcmp(crypt_stat->cipher, | 484 | if (!strcmp(crypt_stat->cipher, |
483 | crypt_stat->mount_crypt_stat->global_default_cipher_name) | 485 | crypt_stat->mount_crypt_stat->global_default_cipher_name) |
484 | && crypt_stat->mount_crypt_stat->global_key_tfm) { | 486 | && crypt_stat->mount_crypt_stat->global_key_tfm) { |
485 | tfm = crypt_stat->mount_crypt_stat->global_key_tfm; | 487 | desc.tfm = crypt_stat->mount_crypt_stat->global_key_tfm; |
486 | tfm_mutex = &crypt_stat->mount_crypt_stat->global_key_tfm_mutex; | 488 | tfm_mutex = &crypt_stat->mount_crypt_stat->global_key_tfm_mutex; |
487 | } else { | 489 | } else { |
488 | tfm = crypto_alloc_tfm(crypt_stat->cipher, | 490 | char *full_alg_name; |
489 | CRYPTO_TFM_REQ_WEAK_KEY); | 491 | |
490 | if (!tfm) { | 492 | rc = ecryptfs_crypto_api_algify_cipher_name(&full_alg_name, |
491 | printk(KERN_ERR "Error allocating crypto context\n"); | 493 | crypt_stat->cipher, |
492 | rc = -ENOMEM; | 494 | "ecb"); |
495 | if (rc) | ||
496 | goto out; | ||
497 | desc.tfm = crypto_alloc_blkcipher(full_alg_name, 0, | ||
498 | CRYPTO_ALG_ASYNC); | ||
499 | kfree(full_alg_name); | ||
500 | if (IS_ERR(desc.tfm)) { | ||
501 | rc = PTR_ERR(desc.tfm); | ||
502 | printk(KERN_ERR "Error allocating crypto context; " | ||
503 | "rc = [%d]\n", rc); | ||
493 | goto out; | 504 | goto out; |
494 | } | 505 | } |
495 | } | 506 | crypto_blkcipher_set_flags(desc.tfm, CRYPTO_TFM_REQ_WEAK_KEY); |
496 | if (password_s_ptr->session_key_encryption_key_bytes | ||
497 | < crypto_tfm_alg_min_keysize(tfm)) { | ||
498 | printk(KERN_WARNING "Session key encryption key is [%d] bytes; " | ||
499 | "minimum keysize for selected cipher is [%d] bytes.\n", | ||
500 | password_s_ptr->session_key_encryption_key_bytes, | ||
501 | crypto_tfm_alg_min_keysize(tfm)); | ||
502 | rc = -EINVAL; | ||
503 | goto out; | ||
504 | } | 507 | } |
505 | if (tfm_mutex) | 508 | if (tfm_mutex) |
506 | mutex_lock(tfm_mutex); | 509 | mutex_lock(tfm_mutex); |
507 | crypto_cipher_setkey(tfm, password_s_ptr->session_key_encryption_key, | 510 | rc = crypto_blkcipher_setkey(desc.tfm, |
508 | crypt_stat->key_size); | 511 | password_s_ptr->session_key_encryption_key, |
512 | crypt_stat->key_size); | ||
513 | if (rc < 0) { | ||
514 | printk(KERN_ERR "Error setting key for crypto context\n"); | ||
515 | rc = -EINVAL; | ||
516 | goto out_free_tfm; | ||
517 | } | ||
509 | /* TODO: virt_to_scatterlist */ | 518 | /* TODO: virt_to_scatterlist */ |
510 | encrypted_session_key = (char *)__get_free_page(GFP_KERNEL); | 519 | encrypted_session_key = (char *)__get_free_page(GFP_KERNEL); |
511 | if (!encrypted_session_key) { | 520 | if (!encrypted_session_key) { |
@@ -531,9 +540,12 @@ static int decrypt_session_key(struct ecryptfs_auth_tok *auth_tok, | |||
531 | auth_tok->session_key.decrypted_key_size = | 540 | auth_tok->session_key.decrypted_key_size = |
532 | auth_tok->session_key.encrypted_key_size; | 541 | auth_tok->session_key.encrypted_key_size; |
533 | dst_sg[0].length = auth_tok->session_key.encrypted_key_size; | 542 | dst_sg[0].length = auth_tok->session_key.encrypted_key_size; |
534 | /* TODO: Handle error condition */ | 543 | rc = crypto_blkcipher_decrypt(&desc, dst_sg, src_sg, |
535 | crypto_cipher_decrypt(tfm, dst_sg, src_sg, | 544 | auth_tok->session_key.encrypted_key_size); |
536 | auth_tok->session_key.encrypted_key_size); | 545 | if (rc) { |
546 | printk(KERN_ERR "Error decrypting; rc = [%d]\n", rc); | ||
547 | goto out_free_memory; | ||
548 | } | ||
537 | auth_tok->session_key.decrypted_key_size = | 549 | auth_tok->session_key.decrypted_key_size = |
538 | auth_tok->session_key.encrypted_key_size; | 550 | auth_tok->session_key.encrypted_key_size; |
539 | memcpy(auth_tok->session_key.decrypted_key, session_key, | 551 | memcpy(auth_tok->session_key.decrypted_key, session_key, |
@@ -546,6 +558,7 @@ static int decrypt_session_key(struct ecryptfs_auth_tok *auth_tok, | |||
546 | if (ecryptfs_verbosity > 0) | 558 | if (ecryptfs_verbosity > 0) |
547 | ecryptfs_dump_hex(crypt_stat->key, | 559 | ecryptfs_dump_hex(crypt_stat->key, |
548 | crypt_stat->key_size); | 560 | crypt_stat->key_size); |
561 | out_free_memory: | ||
549 | memset(encrypted_session_key, 0, PAGE_CACHE_SIZE); | 562 | memset(encrypted_session_key, 0, PAGE_CACHE_SIZE); |
550 | free_page((unsigned long)encrypted_session_key); | 563 | free_page((unsigned long)encrypted_session_key); |
551 | memset(session_key, 0, PAGE_CACHE_SIZE); | 564 | memset(session_key, 0, PAGE_CACHE_SIZE); |
@@ -554,7 +567,7 @@ out_free_tfm: | |||
554 | if (tfm_mutex) | 567 | if (tfm_mutex) |
555 | mutex_unlock(tfm_mutex); | 568 | mutex_unlock(tfm_mutex); |
556 | else | 569 | else |
557 | crypto_free_tfm(tfm); | 570 | crypto_free_blkcipher(desc.tfm); |
558 | out: | 571 | out: |
559 | return rc; | 572 | return rc; |
560 | } | 573 | } |
@@ -803,19 +816,21 @@ write_tag_3_packet(char *dest, size_t max, struct ecryptfs_auth_tok *auth_tok, | |||
803 | struct ecryptfs_crypt_stat *crypt_stat, | 816 | struct ecryptfs_crypt_stat *crypt_stat, |
804 | struct ecryptfs_key_record *key_rec, size_t *packet_size) | 817 | struct ecryptfs_key_record *key_rec, size_t *packet_size) |
805 | { | 818 | { |
806 | int rc = 0; | ||
807 | |||
808 | size_t i; | 819 | size_t i; |
809 | size_t signature_is_valid = 0; | 820 | size_t signature_is_valid = 0; |
810 | size_t encrypted_session_key_valid = 0; | 821 | size_t encrypted_session_key_valid = 0; |
811 | char session_key_encryption_key[ECRYPTFS_MAX_KEY_BYTES]; | 822 | char session_key_encryption_key[ECRYPTFS_MAX_KEY_BYTES]; |
812 | struct scatterlist dest_sg[2]; | 823 | struct scatterlist dest_sg[2]; |
813 | struct scatterlist src_sg[2]; | 824 | struct scatterlist src_sg[2]; |
814 | struct crypto_tfm *tfm = NULL; | ||
815 | struct mutex *tfm_mutex = NULL; | 825 | struct mutex *tfm_mutex = NULL; |
816 | size_t key_rec_size; | 826 | size_t key_rec_size; |
817 | size_t packet_size_length; | 827 | size_t packet_size_length; |
818 | size_t cipher_code; | 828 | size_t cipher_code; |
829 | struct blkcipher_desc desc = { | ||
830 | .tfm = NULL, | ||
831 | .flags = CRYPTO_TFM_REQ_MAY_SLEEP | ||
832 | }; | ||
833 | int rc = 0; | ||
819 | 834 | ||
820 | (*packet_size) = 0; | 835 | (*packet_size) = 0; |
821 | /* Check for a valid signature on the auth_tok */ | 836 | /* Check for a valid signature on the auth_tok */ |
@@ -882,33 +897,48 @@ write_tag_3_packet(char *dest, size_t max, struct ecryptfs_auth_tok *auth_tok, | |||
882 | if (!strcmp(crypt_stat->cipher, | 897 | if (!strcmp(crypt_stat->cipher, |
883 | crypt_stat->mount_crypt_stat->global_default_cipher_name) | 898 | crypt_stat->mount_crypt_stat->global_default_cipher_name) |
884 | && crypt_stat->mount_crypt_stat->global_key_tfm) { | 899 | && crypt_stat->mount_crypt_stat->global_key_tfm) { |
885 | tfm = crypt_stat->mount_crypt_stat->global_key_tfm; | 900 | desc.tfm = crypt_stat->mount_crypt_stat->global_key_tfm; |
886 | tfm_mutex = &crypt_stat->mount_crypt_stat->global_key_tfm_mutex; | 901 | tfm_mutex = &crypt_stat->mount_crypt_stat->global_key_tfm_mutex; |
887 | } else | 902 | } else { |
888 | tfm = crypto_alloc_tfm(crypt_stat->cipher, 0); | 903 | char *full_alg_name; |
889 | if (!tfm) { | 904 | |
890 | ecryptfs_printk(KERN_ERR, "Could not initialize crypto " | 905 | rc = ecryptfs_crypto_api_algify_cipher_name(&full_alg_name, |
891 | "context for cipher [%s]\n", | 906 | crypt_stat->cipher, |
892 | crypt_stat->cipher); | 907 | "ecb"); |
893 | rc = -EINVAL; | 908 | if (rc) |
894 | goto out; | 909 | goto out; |
910 | desc.tfm = crypto_alloc_blkcipher(full_alg_name, 0, | ||
911 | CRYPTO_ALG_ASYNC); | ||
912 | kfree(full_alg_name); | ||
913 | if (IS_ERR(desc.tfm)) { | ||
914 | rc = PTR_ERR(desc.tfm); | ||
915 | ecryptfs_printk(KERN_ERR, "Could not initialize crypto " | ||
916 | "context for cipher [%s]; rc = [%d]\n", | ||
917 | crypt_stat->cipher, rc); | ||
918 | goto out; | ||
919 | } | ||
920 | crypto_blkcipher_set_flags(desc.tfm, CRYPTO_TFM_REQ_WEAK_KEY); | ||
895 | } | 921 | } |
896 | if (tfm_mutex) | 922 | if (tfm_mutex) |
897 | mutex_lock(tfm_mutex); | 923 | mutex_lock(tfm_mutex); |
898 | rc = crypto_cipher_setkey(tfm, session_key_encryption_key, | 924 | rc = crypto_blkcipher_setkey(desc.tfm, session_key_encryption_key, |
899 | crypt_stat->key_size); | 925 | crypt_stat->key_size); |
900 | if (rc < 0) { | 926 | if (rc < 0) { |
901 | if (tfm_mutex) | 927 | if (tfm_mutex) |
902 | mutex_unlock(tfm_mutex); | 928 | mutex_unlock(tfm_mutex); |
903 | ecryptfs_printk(KERN_ERR, "Error setting key for crypto " | 929 | ecryptfs_printk(KERN_ERR, "Error setting key for crypto " |
904 | "context\n"); | 930 | "context; rc = [%d]\n", rc); |
905 | goto out; | 931 | goto out; |
906 | } | 932 | } |
907 | rc = 0; | 933 | rc = 0; |
908 | ecryptfs_printk(KERN_DEBUG, "Encrypting [%d] bytes of the key\n", | 934 | ecryptfs_printk(KERN_DEBUG, "Encrypting [%d] bytes of the key\n", |
909 | crypt_stat->key_size); | 935 | crypt_stat->key_size); |
910 | crypto_cipher_encrypt(tfm, dest_sg, src_sg, | 936 | rc = crypto_blkcipher_encrypt(&desc, dest_sg, src_sg, |
911 | (*key_rec).enc_key_size); | 937 | (*key_rec).enc_key_size); |
938 | if (rc) { | ||
939 | printk(KERN_ERR "Error encrypting; rc = [%d]\n", rc); | ||
940 | goto out; | ||
941 | } | ||
912 | if (tfm_mutex) | 942 | if (tfm_mutex) |
913 | mutex_unlock(tfm_mutex); | 943 | mutex_unlock(tfm_mutex); |
914 | ecryptfs_printk(KERN_DEBUG, "This should be the encrypted key:\n"); | 944 | ecryptfs_printk(KERN_DEBUG, "This should be the encrypted key:\n"); |
@@ -971,8 +1001,8 @@ encrypted_session_key_set: | |||
971 | (*key_rec).enc_key_size); | 1001 | (*key_rec).enc_key_size); |
972 | (*packet_size) += (*key_rec).enc_key_size; | 1002 | (*packet_size) += (*key_rec).enc_key_size; |
973 | out: | 1003 | out: |
974 | if (tfm && !tfm_mutex) | 1004 | if (desc.tfm && !tfm_mutex) |
975 | crypto_free_tfm(tfm); | 1005 | crypto_free_blkcipher(desc.tfm); |
976 | if (rc) | 1006 | if (rc) |
977 | (*packet_size) = 0; | 1007 | (*packet_size) = 0; |
978 | return rc; | 1008 | return rc; |
diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c index 5938a232d11b..a78d87d14baf 100644 --- a/fs/ecryptfs/main.c +++ b/fs/ecryptfs/main.c | |||
@@ -208,7 +208,6 @@ static int ecryptfs_parse_options(struct super_block *sb, char *options) | |||
208 | char *cipher_name_dst; | 208 | char *cipher_name_dst; |
209 | char *cipher_name_src; | 209 | char *cipher_name_src; |
210 | char *cipher_key_bytes_src; | 210 | char *cipher_key_bytes_src; |
211 | struct crypto_tfm *tmp_tfm; | ||
212 | int cipher_name_len; | 211 | int cipher_name_len; |
213 | 212 | ||
214 | if (!options) { | 213 | if (!options) { |
@@ -305,25 +304,19 @@ static int ecryptfs_parse_options(struct super_block *sb, char *options) | |||
305 | = '\0'; | 304 | = '\0'; |
306 | } | 305 | } |
307 | if (!cipher_key_bytes_set) { | 306 | if (!cipher_key_bytes_set) { |
308 | mount_crypt_stat->global_default_cipher_key_size = | 307 | mount_crypt_stat->global_default_cipher_key_size = 0; |
309 | ECRYPTFS_DEFAULT_KEY_BYTES; | ||
310 | ecryptfs_printk(KERN_DEBUG, "Cipher key size was not " | ||
311 | "specified. Defaulting to [%d]\n", | ||
312 | mount_crypt_stat-> | ||
313 | global_default_cipher_key_size); | ||
314 | } | 308 | } |
315 | rc = ecryptfs_process_cipher( | 309 | rc = ecryptfs_process_cipher( |
316 | &tmp_tfm, | ||
317 | &mount_crypt_stat->global_key_tfm, | 310 | &mount_crypt_stat->global_key_tfm, |
318 | mount_crypt_stat->global_default_cipher_name, | 311 | mount_crypt_stat->global_default_cipher_name, |
319 | mount_crypt_stat->global_default_cipher_key_size); | 312 | &mount_crypt_stat->global_default_cipher_key_size); |
320 | if (tmp_tfm) | ||
321 | crypto_free_tfm(tmp_tfm); | ||
322 | if (rc) { | 313 | if (rc) { |
323 | printk(KERN_ERR "Error attempting to initialize cipher [%s] " | 314 | printk(KERN_ERR "Error attempting to initialize cipher [%s] " |
324 | "with key size [%Zd] bytes; rc = [%d]\n", | 315 | "with key size [%Zd] bytes; rc = [%d]\n", |
325 | mount_crypt_stat->global_default_cipher_name, | 316 | mount_crypt_stat->global_default_cipher_name, |
326 | mount_crypt_stat->global_default_cipher_key_size, rc); | 317 | mount_crypt_stat->global_default_cipher_key_size, rc); |
318 | mount_crypt_stat->global_key_tfm = NULL; | ||
319 | mount_crypt_stat->global_auth_tok_key = NULL; | ||
327 | rc = -EINVAL; | 320 | rc = -EINVAL; |
328 | goto out; | 321 | goto out; |
329 | } | 322 | } |
diff --git a/fs/ecryptfs/super.c b/fs/ecryptfs/super.c index c337c0410fb1..825757ae4867 100644 --- a/fs/ecryptfs/super.c +++ b/fs/ecryptfs/super.c | |||
@@ -138,23 +138,6 @@ static void ecryptfs_clear_inode(struct inode *inode) | |||
138 | } | 138 | } |
139 | 139 | ||
140 | /** | 140 | /** |
141 | * ecryptfs_umount_begin | ||
142 | * | ||
143 | * Called in do_umount(). | ||
144 | */ | ||
145 | static void ecryptfs_umount_begin(struct vfsmount *vfsmnt, int flags) | ||
146 | { | ||
147 | struct vfsmount *lower_mnt = | ||
148 | ecryptfs_dentry_to_lower_mnt(vfsmnt->mnt_sb->s_root); | ||
149 | struct super_block *lower_sb; | ||
150 | |||
151 | mntput(lower_mnt); | ||
152 | lower_sb = lower_mnt->mnt_sb; | ||
153 | if (lower_sb->s_op->umount_begin) | ||
154 | lower_sb->s_op->umount_begin(lower_mnt, flags); | ||
155 | } | ||
156 | |||
157 | /** | ||
158 | * ecryptfs_show_options | 141 | * ecryptfs_show_options |
159 | * | 142 | * |
160 | * Prints the directory we are currently mounted over. | 143 | * Prints the directory we are currently mounted over. |
@@ -193,6 +176,5 @@ struct super_operations ecryptfs_sops = { | |||
193 | .statfs = ecryptfs_statfs, | 176 | .statfs = ecryptfs_statfs, |
194 | .remount_fs = NULL, | 177 | .remount_fs = NULL, |
195 | .clear_inode = ecryptfs_clear_inode, | 178 | .clear_inode = ecryptfs_clear_inode, |
196 | .umount_begin = ecryptfs_umount_begin, | ||
197 | .show_options = ecryptfs_show_options | 179 | .show_options = ecryptfs_show_options |
198 | }; | 180 | }; |
diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c index 1e9578052cd3..4fe49c3661b2 100644 --- a/fs/ext4/resize.c +++ b/fs/ext4/resize.c | |||
@@ -69,44 +69,49 @@ static int verify_group_input(struct super_block *sb, | |||
69 | else if (outside(input->block_bitmap, start, end)) | 69 | else if (outside(input->block_bitmap, start, end)) |
70 | ext4_warning(sb, __FUNCTION__, | 70 | ext4_warning(sb, __FUNCTION__, |
71 | "Block bitmap not in group (block %llu)", | 71 | "Block bitmap not in group (block %llu)", |
72 | input->block_bitmap); | 72 | (unsigned long long)input->block_bitmap); |
73 | else if (outside(input->inode_bitmap, start, end)) | 73 | else if (outside(input->inode_bitmap, start, end)) |
74 | ext4_warning(sb, __FUNCTION__, | 74 | ext4_warning(sb, __FUNCTION__, |
75 | "Inode bitmap not in group (block %llu)", | 75 | "Inode bitmap not in group (block %llu)", |
76 | input->inode_bitmap); | 76 | (unsigned long long)input->inode_bitmap); |
77 | else if (outside(input->inode_table, start, end) || | 77 | else if (outside(input->inode_table, start, end) || |
78 | outside(itend - 1, start, end)) | 78 | outside(itend - 1, start, end)) |
79 | ext4_warning(sb, __FUNCTION__, | 79 | ext4_warning(sb, __FUNCTION__, |
80 | "Inode table not in group (blocks %llu-%llu)", | 80 | "Inode table not in group (blocks %llu-%llu)", |
81 | input->inode_table, itend - 1); | 81 | (unsigned long long)input->inode_table, itend - 1); |
82 | else if (input->inode_bitmap == input->block_bitmap) | 82 | else if (input->inode_bitmap == input->block_bitmap) |
83 | ext4_warning(sb, __FUNCTION__, | 83 | ext4_warning(sb, __FUNCTION__, |
84 | "Block bitmap same as inode bitmap (%llu)", | 84 | "Block bitmap same as inode bitmap (%llu)", |
85 | input->block_bitmap); | 85 | (unsigned long long)input->block_bitmap); |
86 | else if (inside(input->block_bitmap, input->inode_table, itend)) | 86 | else if (inside(input->block_bitmap, input->inode_table, itend)) |
87 | ext4_warning(sb, __FUNCTION__, | 87 | ext4_warning(sb, __FUNCTION__, |
88 | "Block bitmap (%llu) in inode table (%llu-%llu)", | 88 | "Block bitmap (%llu) in inode table (%llu-%llu)", |
89 | input->block_bitmap, input->inode_table, itend-1); | 89 | (unsigned long long)input->block_bitmap, |
90 | (unsigned long long)input->inode_table, itend - 1); | ||
90 | else if (inside(input->inode_bitmap, input->inode_table, itend)) | 91 | else if (inside(input->inode_bitmap, input->inode_table, itend)) |
91 | ext4_warning(sb, __FUNCTION__, | 92 | ext4_warning(sb, __FUNCTION__, |
92 | "Inode bitmap (%llu) in inode table (%llu-%llu)", | 93 | "Inode bitmap (%llu) in inode table (%llu-%llu)", |
93 | input->inode_bitmap, input->inode_table, itend-1); | 94 | (unsigned long long)input->inode_bitmap, |
95 | (unsigned long long)input->inode_table, itend - 1); | ||
94 | else if (inside(input->block_bitmap, start, metaend)) | 96 | else if (inside(input->block_bitmap, start, metaend)) |
95 | ext4_warning(sb, __FUNCTION__, | 97 | ext4_warning(sb, __FUNCTION__, |
96 | "Block bitmap (%llu) in GDT table" | 98 | "Block bitmap (%llu) in GDT table" |
97 | " (%llu-%llu)", | 99 | " (%llu-%llu)", |
98 | input->block_bitmap, start, metaend - 1); | 100 | (unsigned long long)input->block_bitmap, |
101 | start, metaend - 1); | ||
99 | else if (inside(input->inode_bitmap, start, metaend)) | 102 | else if (inside(input->inode_bitmap, start, metaend)) |
100 | ext4_warning(sb, __FUNCTION__, | 103 | ext4_warning(sb, __FUNCTION__, |
101 | "Inode bitmap (%llu) in GDT table" | 104 | "Inode bitmap (%llu) in GDT table" |
102 | " (%llu-%llu)", | 105 | " (%llu-%llu)", |
103 | input->inode_bitmap, start, metaend - 1); | 106 | (unsigned long long)input->inode_bitmap, |
107 | start, metaend - 1); | ||
104 | else if (inside(input->inode_table, start, metaend) || | 108 | else if (inside(input->inode_table, start, metaend) || |
105 | inside(itend - 1, start, metaend)) | 109 | inside(itend - 1, start, metaend)) |
106 | ext4_warning(sb, __FUNCTION__, | 110 | ext4_warning(sb, __FUNCTION__, |
107 | "Inode table (%llu-%llu) overlaps" | 111 | "Inode table (%llu-%llu) overlaps" |
108 | "GDT table (%llu-%llu)", | 112 | "GDT table (%llu-%llu)", |
109 | input->inode_table, itend - 1, start, metaend - 1); | 113 | (unsigned long long)input->inode_table, |
114 | itend - 1, start, metaend - 1); | ||
110 | else | 115 | else |
111 | err = 0; | 116 | err = 0; |
112 | brelse(bh); | 117 | brelse(bh); |
diff --git a/fs/fat/file.c b/fs/fat/file.c index 8337451e7897..0aa813d944a6 100644 --- a/fs/fat/file.c +++ b/fs/fat/file.c | |||
@@ -303,7 +303,17 @@ void fat_truncate(struct inode *inode) | |||
303 | fat_flush_inodes(inode->i_sb, inode, NULL); | 303 | fat_flush_inodes(inode->i_sb, inode, NULL); |
304 | } | 304 | } |
305 | 305 | ||
306 | int fat_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) | ||
307 | { | ||
308 | struct inode *inode = dentry->d_inode; | ||
309 | generic_fillattr(inode, stat); | ||
310 | stat->blksize = MSDOS_SB(inode->i_sb)->cluster_size; | ||
311 | return 0; | ||
312 | } | ||
313 | EXPORT_SYMBOL_GPL(fat_getattr); | ||
314 | |||
306 | struct inode_operations fat_file_inode_operations = { | 315 | struct inode_operations fat_file_inode_operations = { |
307 | .truncate = fat_truncate, | 316 | .truncate = fat_truncate, |
308 | .setattr = fat_notify_change, | 317 | .setattr = fat_notify_change, |
318 | .getattr = fat_getattr, | ||
309 | }; | 319 | }; |
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index cfc8f81e60d0..c71a6c092ad9 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c | |||
@@ -138,6 +138,7 @@ static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd) | |||
138 | struct fuse_entry_out outarg; | 138 | struct fuse_entry_out outarg; |
139 | struct fuse_conn *fc; | 139 | struct fuse_conn *fc; |
140 | struct fuse_req *req; | 140 | struct fuse_req *req; |
141 | struct fuse_req *forget_req; | ||
141 | struct dentry *parent; | 142 | struct dentry *parent; |
142 | 143 | ||
143 | /* Doesn't hurt to "reset" the validity timeout */ | 144 | /* Doesn't hurt to "reset" the validity timeout */ |
@@ -152,25 +153,33 @@ static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd) | |||
152 | if (IS_ERR(req)) | 153 | if (IS_ERR(req)) |
153 | return 0; | 154 | return 0; |
154 | 155 | ||
156 | forget_req = fuse_get_req(fc); | ||
157 | if (IS_ERR(forget_req)) { | ||
158 | fuse_put_request(fc, req); | ||
159 | return 0; | ||
160 | } | ||
161 | |||
155 | parent = dget_parent(entry); | 162 | parent = dget_parent(entry); |
156 | fuse_lookup_init(req, parent->d_inode, entry, &outarg); | 163 | fuse_lookup_init(req, parent->d_inode, entry, &outarg); |
157 | request_send(fc, req); | 164 | request_send(fc, req); |
158 | dput(parent); | 165 | dput(parent); |
159 | err = req->out.h.error; | 166 | err = req->out.h.error; |
167 | fuse_put_request(fc, req); | ||
160 | /* Zero nodeid is same as -ENOENT */ | 168 | /* Zero nodeid is same as -ENOENT */ |
161 | if (!err && !outarg.nodeid) | 169 | if (!err && !outarg.nodeid) |
162 | err = -ENOENT; | 170 | err = -ENOENT; |
163 | if (!err) { | 171 | if (!err) { |
164 | struct fuse_inode *fi = get_fuse_inode(inode); | 172 | struct fuse_inode *fi = get_fuse_inode(inode); |
165 | if (outarg.nodeid != get_node_id(inode)) { | 173 | if (outarg.nodeid != get_node_id(inode)) { |
166 | fuse_send_forget(fc, req, outarg.nodeid, 1); | 174 | fuse_send_forget(fc, forget_req, |
175 | outarg.nodeid, 1); | ||
167 | return 0; | 176 | return 0; |
168 | } | 177 | } |
169 | spin_lock(&fc->lock); | 178 | spin_lock(&fc->lock); |
170 | fi->nlookup ++; | 179 | fi->nlookup ++; |
171 | spin_unlock(&fc->lock); | 180 | spin_unlock(&fc->lock); |
172 | } | 181 | } |
173 | fuse_put_request(fc, req); | 182 | fuse_put_request(fc, forget_req); |
174 | if (err || (outarg.attr.mode ^ inode->i_mode) & S_IFMT) | 183 | if (err || (outarg.attr.mode ^ inode->i_mode) & S_IFMT) |
175 | return 0; | 184 | return 0; |
176 | 185 | ||
@@ -221,6 +230,7 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry, | |||
221 | struct inode *inode = NULL; | 230 | struct inode *inode = NULL; |
222 | struct fuse_conn *fc = get_fuse_conn(dir); | 231 | struct fuse_conn *fc = get_fuse_conn(dir); |
223 | struct fuse_req *req; | 232 | struct fuse_req *req; |
233 | struct fuse_req *forget_req; | ||
224 | 234 | ||
225 | if (entry->d_name.len > FUSE_NAME_MAX) | 235 | if (entry->d_name.len > FUSE_NAME_MAX) |
226 | return ERR_PTR(-ENAMETOOLONG); | 236 | return ERR_PTR(-ENAMETOOLONG); |
@@ -229,9 +239,16 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry, | |||
229 | if (IS_ERR(req)) | 239 | if (IS_ERR(req)) |
230 | return ERR_PTR(PTR_ERR(req)); | 240 | return ERR_PTR(PTR_ERR(req)); |
231 | 241 | ||
242 | forget_req = fuse_get_req(fc); | ||
243 | if (IS_ERR(forget_req)) { | ||
244 | fuse_put_request(fc, req); | ||
245 | return ERR_PTR(PTR_ERR(forget_req)); | ||
246 | } | ||
247 | |||
232 | fuse_lookup_init(req, dir, entry, &outarg); | 248 | fuse_lookup_init(req, dir, entry, &outarg); |
233 | request_send(fc, req); | 249 | request_send(fc, req); |
234 | err = req->out.h.error; | 250 | err = req->out.h.error; |
251 | fuse_put_request(fc, req); | ||
235 | /* Zero nodeid is same as -ENOENT, but with valid timeout */ | 252 | /* Zero nodeid is same as -ENOENT, but with valid timeout */ |
236 | if (!err && outarg.nodeid && | 253 | if (!err && outarg.nodeid && |
237 | (invalid_nodeid(outarg.nodeid) || !valid_mode(outarg.attr.mode))) | 254 | (invalid_nodeid(outarg.nodeid) || !valid_mode(outarg.attr.mode))) |
@@ -240,11 +257,11 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry, | |||
240 | inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation, | 257 | inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation, |
241 | &outarg.attr); | 258 | &outarg.attr); |
242 | if (!inode) { | 259 | if (!inode) { |
243 | fuse_send_forget(fc, req, outarg.nodeid, 1); | 260 | fuse_send_forget(fc, forget_req, outarg.nodeid, 1); |
244 | return ERR_PTR(-ENOMEM); | 261 | return ERR_PTR(-ENOMEM); |
245 | } | 262 | } |
246 | } | 263 | } |
247 | fuse_put_request(fc, req); | 264 | fuse_put_request(fc, forget_req); |
248 | if (err && err != -ENOENT) | 265 | if (err && err != -ENOENT) |
249 | return ERR_PTR(err); | 266 | return ERR_PTR(err); |
250 | 267 | ||
@@ -388,6 +405,13 @@ static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req, | |||
388 | struct fuse_entry_out outarg; | 405 | struct fuse_entry_out outarg; |
389 | struct inode *inode; | 406 | struct inode *inode; |
390 | int err; | 407 | int err; |
408 | struct fuse_req *forget_req; | ||
409 | |||
410 | forget_req = fuse_get_req(fc); | ||
411 | if (IS_ERR(forget_req)) { | ||
412 | fuse_put_request(fc, req); | ||
413 | return PTR_ERR(forget_req); | ||
414 | } | ||
391 | 415 | ||
392 | req->in.h.nodeid = get_node_id(dir); | 416 | req->in.h.nodeid = get_node_id(dir); |
393 | req->out.numargs = 1; | 417 | req->out.numargs = 1; |
@@ -395,24 +419,24 @@ static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req, | |||
395 | req->out.args[0].value = &outarg; | 419 | req->out.args[0].value = &outarg; |
396 | request_send(fc, req); | 420 | request_send(fc, req); |
397 | err = req->out.h.error; | 421 | err = req->out.h.error; |
398 | if (err) { | 422 | fuse_put_request(fc, req); |
399 | fuse_put_request(fc, req); | 423 | if (err) |
400 | return err; | 424 | goto out_put_forget_req; |
401 | } | 425 | |
402 | err = -EIO; | 426 | err = -EIO; |
403 | if (invalid_nodeid(outarg.nodeid)) | 427 | if (invalid_nodeid(outarg.nodeid)) |
404 | goto out_put_request; | 428 | goto out_put_forget_req; |
405 | 429 | ||
406 | if ((outarg.attr.mode ^ mode) & S_IFMT) | 430 | if ((outarg.attr.mode ^ mode) & S_IFMT) |
407 | goto out_put_request; | 431 | goto out_put_forget_req; |
408 | 432 | ||
409 | inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation, | 433 | inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation, |
410 | &outarg.attr); | 434 | &outarg.attr); |
411 | if (!inode) { | 435 | if (!inode) { |
412 | fuse_send_forget(fc, req, outarg.nodeid, 1); | 436 | fuse_send_forget(fc, forget_req, outarg.nodeid, 1); |
413 | return -ENOMEM; | 437 | return -ENOMEM; |
414 | } | 438 | } |
415 | fuse_put_request(fc, req); | 439 | fuse_put_request(fc, forget_req); |
416 | 440 | ||
417 | if (S_ISDIR(inode->i_mode)) { | 441 | if (S_ISDIR(inode->i_mode)) { |
418 | struct dentry *alias; | 442 | struct dentry *alias; |
@@ -434,8 +458,8 @@ static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req, | |||
434 | fuse_invalidate_attr(dir); | 458 | fuse_invalidate_attr(dir); |
435 | return 0; | 459 | return 0; |
436 | 460 | ||
437 | out_put_request: | 461 | out_put_forget_req: |
438 | fuse_put_request(fc, req); | 462 | fuse_put_request(fc, forget_req); |
439 | return err; | 463 | return err; |
440 | } | 464 | } |
441 | 465 | ||
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 2bb5ace3882d..763a50daf1c0 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c | |||
@@ -397,14 +397,14 @@ static int fuse_readpages(struct file *file, struct address_space *mapping, | |||
397 | 397 | ||
398 | err = -EIO; | 398 | err = -EIO; |
399 | if (is_bad_inode(inode)) | 399 | if (is_bad_inode(inode)) |
400 | goto clean_pages_up; | 400 | goto out; |
401 | 401 | ||
402 | data.file = file; | 402 | data.file = file; |
403 | data.inode = inode; | 403 | data.inode = inode; |
404 | data.req = fuse_get_req(fc); | 404 | data.req = fuse_get_req(fc); |
405 | err = PTR_ERR(data.req); | 405 | err = PTR_ERR(data.req); |
406 | if (IS_ERR(data.req)) | 406 | if (IS_ERR(data.req)) |
407 | goto clean_pages_up; | 407 | goto out; |
408 | 408 | ||
409 | err = read_cache_pages(mapping, pages, fuse_readpages_fill, &data); | 409 | err = read_cache_pages(mapping, pages, fuse_readpages_fill, &data); |
410 | if (!err) { | 410 | if (!err) { |
@@ -413,10 +413,7 @@ static int fuse_readpages(struct file *file, struct address_space *mapping, | |||
413 | else | 413 | else |
414 | fuse_put_request(fc, data.req); | 414 | fuse_put_request(fc, data.req); |
415 | } | 415 | } |
416 | return err; | 416 | out: |
417 | |||
418 | clean_pages_up: | ||
419 | put_pages_list(pages); | ||
420 | return err; | 417 | return err; |
421 | } | 418 | } |
422 | 419 | ||
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index 57c43ac47925..d470e5286ecd 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c | |||
@@ -157,6 +157,9 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, struct gfs2_inum *inum, | |||
157 | struct gfs2_glock *io_gl; | 157 | struct gfs2_glock *io_gl; |
158 | int error; | 158 | int error; |
159 | 159 | ||
160 | if (!inode) | ||
161 | return ERR_PTR(-ENOBUFS); | ||
162 | |||
160 | if (inode->i_state & I_NEW) { | 163 | if (inode->i_state & I_NEW) { |
161 | struct gfs2_sbd *sdp = GFS2_SB(inode); | 164 | struct gfs2_sbd *sdp = GFS2_SB(inode); |
162 | umode_t mode = DT2IF(type); | 165 | umode_t mode = DT2IF(type); |
diff --git a/fs/gfs2/main.c b/fs/gfs2/main.c index 21508a13bb78..9889c1eacec1 100644 --- a/fs/gfs2/main.c +++ b/fs/gfs2/main.c | |||
@@ -84,8 +84,8 @@ static int __init init_gfs2_fs(void) | |||
84 | 84 | ||
85 | gfs2_inode_cachep = kmem_cache_create("gfs2_inode", | 85 | gfs2_inode_cachep = kmem_cache_create("gfs2_inode", |
86 | sizeof(struct gfs2_inode), | 86 | sizeof(struct gfs2_inode), |
87 | 0, (SLAB_RECLAIM_ACCOUNT| | 87 | 0, SLAB_RECLAIM_ACCOUNT| |
88 | SLAB_PANIC|SLAB_MEM_SPREAD), | 88 | SLAB_MEM_SPREAD, |
89 | gfs2_init_inode_once, NULL); | 89 | gfs2_init_inode_once, NULL); |
90 | if (!gfs2_inode_cachep) | 90 | if (!gfs2_inode_cachep) |
91 | goto fail; | 91 | goto fail; |
diff --git a/fs/gfs2/ops_address.c b/fs/gfs2/ops_address.c index 8d5963c7e123..015640b3f123 100644 --- a/fs/gfs2/ops_address.c +++ b/fs/gfs2/ops_address.c | |||
@@ -337,13 +337,6 @@ out: | |||
337 | out_noerror: | 337 | out_noerror: |
338 | ret = 0; | 338 | ret = 0; |
339 | out_unlock: | 339 | out_unlock: |
340 | /* unlock all pages, we can't do any I/O right now */ | ||
341 | for (page_idx = 0; page_idx < nr_pages; page_idx++) { | ||
342 | struct page *page = list_entry(pages->prev, struct page, lru); | ||
343 | list_del(&page->lru); | ||
344 | unlock_page(page); | ||
345 | page_cache_release(page); | ||
346 | } | ||
347 | if (do_unlock) | 340 | if (do_unlock) |
348 | gfs2_holder_uninit(&gh); | 341 | gfs2_holder_uninit(&gh); |
349 | goto out; | 342 | goto out; |
diff --git a/fs/gfs2/ops_super.c b/fs/gfs2/ops_super.c index 06f06f7773d0..b47d9598c047 100644 --- a/fs/gfs2/ops_super.c +++ b/fs/gfs2/ops_super.c | |||
@@ -138,16 +138,27 @@ static void gfs2_put_super(struct super_block *sb) | |||
138 | } | 138 | } |
139 | 139 | ||
140 | /** | 140 | /** |
141 | * gfs2_write_super - disk commit all incore transactions | 141 | * gfs2_write_super |
142 | * @sb: the filesystem | 142 | * @sb: the superblock |
143 | * | 143 | * |
144 | * This function is called every time sync(2) is called. | ||
145 | * After this exits, all dirty buffers are synced. | ||
146 | */ | 144 | */ |
147 | 145 | ||
148 | static void gfs2_write_super(struct super_block *sb) | 146 | static void gfs2_write_super(struct super_block *sb) |
149 | { | 147 | { |
148 | sb->s_dirt = 0; | ||
149 | } | ||
150 | |||
151 | /** | ||
152 | * gfs2_sync_fs - sync the filesystem | ||
153 | * @sb: the superblock | ||
154 | * | ||
155 | * Flushes the log to disk. | ||
156 | */ | ||
157 | static int gfs2_sync_fs(struct super_block *sb, int wait) | ||
158 | { | ||
159 | sb->s_dirt = 0; | ||
150 | gfs2_log_flush(sb->s_fs_info, NULL); | 160 | gfs2_log_flush(sb->s_fs_info, NULL); |
161 | return 0; | ||
151 | } | 162 | } |
152 | 163 | ||
153 | /** | 164 | /** |
@@ -452,17 +463,18 @@ static void gfs2_destroy_inode(struct inode *inode) | |||
452 | } | 463 | } |
453 | 464 | ||
454 | struct super_operations gfs2_super_ops = { | 465 | struct super_operations gfs2_super_ops = { |
455 | .alloc_inode = gfs2_alloc_inode, | 466 | .alloc_inode = gfs2_alloc_inode, |
456 | .destroy_inode = gfs2_destroy_inode, | 467 | .destroy_inode = gfs2_destroy_inode, |
457 | .write_inode = gfs2_write_inode, | 468 | .write_inode = gfs2_write_inode, |
458 | .delete_inode = gfs2_delete_inode, | 469 | .delete_inode = gfs2_delete_inode, |
459 | .put_super = gfs2_put_super, | 470 | .put_super = gfs2_put_super, |
460 | .write_super = gfs2_write_super, | 471 | .write_super = gfs2_write_super, |
461 | .write_super_lockfs = gfs2_write_super_lockfs, | 472 | .sync_fs = gfs2_sync_fs, |
462 | .unlockfs = gfs2_unlockfs, | 473 | .write_super_lockfs = gfs2_write_super_lockfs, |
463 | .statfs = gfs2_statfs, | 474 | .unlockfs = gfs2_unlockfs, |
464 | .remount_fs = gfs2_remount_fs, | 475 | .statfs = gfs2_statfs, |
465 | .clear_inode = gfs2_clear_inode, | 476 | .remount_fs = gfs2_remount_fs, |
466 | .show_options = gfs2_show_options, | 477 | .clear_inode = gfs2_clear_inode, |
478 | .show_options = gfs2_show_options, | ||
467 | }; | 479 | }; |
468 | 480 | ||
diff --git a/fs/hfs/super.c b/fs/hfs/super.c index d43b4fcc8ad3..85b17b3fa4a0 100644 --- a/fs/hfs/super.c +++ b/fs/hfs/super.c | |||
@@ -390,11 +390,13 @@ static int hfs_fill_super(struct super_block *sb, void *data, int silent) | |||
390 | hfs_find_exit(&fd); | 390 | hfs_find_exit(&fd); |
391 | goto bail_no_root; | 391 | goto bail_no_root; |
392 | } | 392 | } |
393 | res = -EINVAL; | ||
393 | root_inode = hfs_iget(sb, &fd.search_key->cat, &rec); | 394 | root_inode = hfs_iget(sb, &fd.search_key->cat, &rec); |
394 | hfs_find_exit(&fd); | 395 | hfs_find_exit(&fd); |
395 | if (!root_inode) | 396 | if (!root_inode) |
396 | goto bail_no_root; | 397 | goto bail_no_root; |
397 | 398 | ||
399 | res = -ENOMEM; | ||
398 | sb->s_root = d_alloc_root(root_inode); | 400 | sb->s_root = d_alloc_root(root_inode); |
399 | if (!sb->s_root) | 401 | if (!sb->s_root) |
400 | goto bail_iput; | 402 | goto bail_iput; |
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index 4ee3f006b861..7f4756963d05 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c | |||
@@ -62,24 +62,19 @@ static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma) | |||
62 | loff_t len, vma_len; | 62 | loff_t len, vma_len; |
63 | int ret; | 63 | int ret; |
64 | 64 | ||
65 | if (vma->vm_pgoff & (HPAGE_SIZE / PAGE_SIZE - 1)) | 65 | /* |
66 | return -EINVAL; | 66 | * vma alignment has already been checked by prepare_hugepage_range. |
67 | 67 | * If you add any error returns here, do so after setting VM_HUGETLB, | |
68 | if (vma->vm_start & ~HPAGE_MASK) | 68 | * so is_vm_hugetlb_page tests below unmap_region go the right way |
69 | return -EINVAL; | 69 | * when do_mmap_pgoff unwinds (may be important on powerpc and ia64). |
70 | 70 | */ | |
71 | if (vma->vm_end & ~HPAGE_MASK) | 71 | vma->vm_flags |= VM_HUGETLB | VM_RESERVED; |
72 | return -EINVAL; | 72 | vma->vm_ops = &hugetlb_vm_ops; |
73 | |||
74 | if (vma->vm_end - vma->vm_start < HPAGE_SIZE) | ||
75 | return -EINVAL; | ||
76 | 73 | ||
77 | vma_len = (loff_t)(vma->vm_end - vma->vm_start); | 74 | vma_len = (loff_t)(vma->vm_end - vma->vm_start); |
78 | 75 | ||
79 | mutex_lock(&inode->i_mutex); | 76 | mutex_lock(&inode->i_mutex); |
80 | file_accessed(file); | 77 | file_accessed(file); |
81 | vma->vm_flags |= VM_HUGETLB | VM_RESERVED; | ||
82 | vma->vm_ops = &hugetlb_vm_ops; | ||
83 | 78 | ||
84 | ret = -ENOMEM; | 79 | ret = -ENOMEM; |
85 | len = vma_len + ((loff_t)vma->vm_pgoff << PAGE_SHIFT); | 80 | len = vma_len + ((loff_t)vma->vm_pgoff << PAGE_SHIFT); |
@@ -271,26 +266,24 @@ static void hugetlbfs_drop_inode(struct inode *inode) | |||
271 | hugetlbfs_forget_inode(inode); | 266 | hugetlbfs_forget_inode(inode); |
272 | } | 267 | } |
273 | 268 | ||
274 | /* | ||
275 | * h_pgoff is in HPAGE_SIZE units. | ||
276 | * vma->vm_pgoff is in PAGE_SIZE units. | ||
277 | */ | ||
278 | static inline void | 269 | static inline void |
279 | hugetlb_vmtruncate_list(struct prio_tree_root *root, unsigned long h_pgoff) | 270 | hugetlb_vmtruncate_list(struct prio_tree_root *root, pgoff_t pgoff) |
280 | { | 271 | { |
281 | struct vm_area_struct *vma; | 272 | struct vm_area_struct *vma; |
282 | struct prio_tree_iter iter; | 273 | struct prio_tree_iter iter; |
283 | 274 | ||
284 | vma_prio_tree_foreach(vma, &iter, root, h_pgoff, ULONG_MAX) { | 275 | vma_prio_tree_foreach(vma, &iter, root, pgoff, ULONG_MAX) { |
285 | unsigned long h_vm_pgoff; | ||
286 | unsigned long v_offset; | 276 | unsigned long v_offset; |
287 | 277 | ||
288 | h_vm_pgoff = vma->vm_pgoff >> (HPAGE_SHIFT - PAGE_SHIFT); | ||
289 | v_offset = (h_pgoff - h_vm_pgoff) << HPAGE_SHIFT; | ||
290 | /* | 278 | /* |
291 | * Is this VMA fully outside the truncation point? | 279 | * Can the expression below overflow on 32-bit arches? |
280 | * No, because the prio_tree returns us only those vmas | ||
281 | * which overlap the truncated area starting at pgoff, | ||
282 | * and no vma on a 32-bit arch can span beyond the 4GB. | ||
292 | */ | 283 | */ |
293 | if (h_vm_pgoff >= h_pgoff) | 284 | if (vma->vm_pgoff < pgoff) |
285 | v_offset = (pgoff - vma->vm_pgoff) << PAGE_SHIFT; | ||
286 | else | ||
294 | v_offset = 0; | 287 | v_offset = 0; |
295 | 288 | ||
296 | __unmap_hugepage_range(vma, | 289 | __unmap_hugepage_range(vma, |
@@ -303,14 +296,14 @@ hugetlb_vmtruncate_list(struct prio_tree_root *root, unsigned long h_pgoff) | |||
303 | */ | 296 | */ |
304 | static int hugetlb_vmtruncate(struct inode *inode, loff_t offset) | 297 | static int hugetlb_vmtruncate(struct inode *inode, loff_t offset) |
305 | { | 298 | { |
306 | unsigned long pgoff; | 299 | pgoff_t pgoff; |
307 | struct address_space *mapping = inode->i_mapping; | 300 | struct address_space *mapping = inode->i_mapping; |
308 | 301 | ||
309 | if (offset > inode->i_size) | 302 | if (offset > inode->i_size) |
310 | return -EINVAL; | 303 | return -EINVAL; |
311 | 304 | ||
312 | BUG_ON(offset & ~HPAGE_MASK); | 305 | BUG_ON(offset & ~HPAGE_MASK); |
313 | pgoff = offset >> HPAGE_SHIFT; | 306 | pgoff = offset >> PAGE_SHIFT; |
314 | 307 | ||
315 | inode->i_size = offset; | 308 | inode->i_size = offset; |
316 | spin_lock(&mapping->i_mmap_lock); | 309 | spin_lock(&mapping->i_mmap_lock); |
@@ -624,7 +617,6 @@ hugetlbfs_parse_options(char *options, struct hugetlbfs_config *pconfig) | |||
624 | do_div(size, 100); | 617 | do_div(size, 100); |
625 | rest++; | 618 | rest++; |
626 | } | 619 | } |
627 | size &= HPAGE_MASK; | ||
628 | pconfig->nr_blocks = (size >> HPAGE_SHIFT); | 620 | pconfig->nr_blocks = (size >> HPAGE_SHIFT); |
629 | value = rest; | 621 | value = rest; |
630 | } else if (!strcmp(opt,"nr_inodes")) { | 622 | } else if (!strcmp(opt,"nr_inodes")) { |
diff --git a/fs/inode.c b/fs/inode.c index d9a21d122926..26cdb115ce67 100644 --- a/fs/inode.c +++ b/fs/inode.c | |||
@@ -1306,6 +1306,42 @@ void wake_up_inode(struct inode *inode) | |||
1306 | wake_up_bit(&inode->i_state, __I_LOCK); | 1306 | wake_up_bit(&inode->i_state, __I_LOCK); |
1307 | } | 1307 | } |
1308 | 1308 | ||
1309 | /* | ||
1310 | * We rarely want to lock two inodes that do not have a parent/child | ||
1311 | * relationship (such as directory, child inode) simultaneously. The | ||
1312 | * vast majority of file systems should be able to get along fine | ||
1313 | * without this. Do not use these functions except as a last resort. | ||
1314 | */ | ||
1315 | void inode_double_lock(struct inode *inode1, struct inode *inode2) | ||
1316 | { | ||
1317 | if (inode1 == NULL || inode2 == NULL || inode1 == inode2) { | ||
1318 | if (inode1) | ||
1319 | mutex_lock(&inode1->i_mutex); | ||
1320 | else if (inode2) | ||
1321 | mutex_lock(&inode2->i_mutex); | ||
1322 | return; | ||
1323 | } | ||
1324 | |||
1325 | if (inode1 < inode2) { | ||
1326 | mutex_lock_nested(&inode1->i_mutex, I_MUTEX_PARENT); | ||
1327 | mutex_lock_nested(&inode2->i_mutex, I_MUTEX_CHILD); | ||
1328 | } else { | ||
1329 | mutex_lock_nested(&inode2->i_mutex, I_MUTEX_PARENT); | ||
1330 | mutex_lock_nested(&inode1->i_mutex, I_MUTEX_CHILD); | ||
1331 | } | ||
1332 | } | ||
1333 | EXPORT_SYMBOL(inode_double_lock); | ||
1334 | |||
1335 | void inode_double_unlock(struct inode *inode1, struct inode *inode2) | ||
1336 | { | ||
1337 | if (inode1) | ||
1338 | mutex_unlock(&inode1->i_mutex); | ||
1339 | |||
1340 | if (inode2 && inode2 != inode1) | ||
1341 | mutex_unlock(&inode2->i_mutex); | ||
1342 | } | ||
1343 | EXPORT_SYMBOL(inode_double_unlock); | ||
1344 | |||
1309 | static __initdata unsigned long ihash_entries; | 1345 | static __initdata unsigned long ihash_entries; |
1310 | static int __init set_ihash_entries(char *str) | 1346 | static int __init set_ihash_entries(char *str) |
1311 | { | 1347 | { |
diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c index d5c63047a8b3..4f82bcd63e48 100644 --- a/fs/jbd/transaction.c +++ b/fs/jbd/transaction.c | |||
@@ -967,6 +967,13 @@ int journal_dirty_data(handle_t *handle, struct buffer_head *bh) | |||
967 | */ | 967 | */ |
968 | jbd_lock_bh_state(bh); | 968 | jbd_lock_bh_state(bh); |
969 | spin_lock(&journal->j_list_lock); | 969 | spin_lock(&journal->j_list_lock); |
970 | |||
971 | /* Now that we have bh_state locked, are we really still mapped? */ | ||
972 | if (!buffer_mapped(bh)) { | ||
973 | JBUFFER_TRACE(jh, "unmapped buffer, bailing out"); | ||
974 | goto no_journal; | ||
975 | } | ||
976 | |||
970 | if (jh->b_transaction) { | 977 | if (jh->b_transaction) { |
971 | JBUFFER_TRACE(jh, "has transaction"); | 978 | JBUFFER_TRACE(jh, "has transaction"); |
972 | if (jh->b_transaction != handle->h_transaction) { | 979 | if (jh->b_transaction != handle->h_transaction) { |
@@ -1028,6 +1035,11 @@ int journal_dirty_data(handle_t *handle, struct buffer_head *bh) | |||
1028 | sync_dirty_buffer(bh); | 1035 | sync_dirty_buffer(bh); |
1029 | jbd_lock_bh_state(bh); | 1036 | jbd_lock_bh_state(bh); |
1030 | spin_lock(&journal->j_list_lock); | 1037 | spin_lock(&journal->j_list_lock); |
1038 | /* Since we dropped the lock... */ | ||
1039 | if (!buffer_mapped(bh)) { | ||
1040 | JBUFFER_TRACE(jh, "buffer got unmapped"); | ||
1041 | goto no_journal; | ||
1042 | } | ||
1031 | /* The buffer may become locked again at any | 1043 | /* The buffer may become locked again at any |
1032 | time if it is redirtied */ | 1044 | time if it is redirtied */ |
1033 | } | 1045 | } |
@@ -1824,6 +1836,7 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh) | |||
1824 | } | 1836 | } |
1825 | } | 1837 | } |
1826 | } else if (transaction == journal->j_committing_transaction) { | 1838 | } else if (transaction == journal->j_committing_transaction) { |
1839 | JBUFFER_TRACE(jh, "on committing transaction"); | ||
1827 | if (jh->b_jlist == BJ_Locked) { | 1840 | if (jh->b_jlist == BJ_Locked) { |
1828 | /* | 1841 | /* |
1829 | * The buffer is on the committing transaction's locked | 1842 | * The buffer is on the committing transaction's locked |
@@ -1838,7 +1851,6 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh) | |||
1838 | * can remove it's next_transaction pointer from the | 1851 | * can remove it's next_transaction pointer from the |
1839 | * running transaction if that is set, but nothing | 1852 | * running transaction if that is set, but nothing |
1840 | * else. */ | 1853 | * else. */ |
1841 | JBUFFER_TRACE(jh, "on committing transaction"); | ||
1842 | set_buffer_freed(bh); | 1854 | set_buffer_freed(bh); |
1843 | if (jh->b_next_transaction) { | 1855 | if (jh->b_next_transaction) { |
1844 | J_ASSERT(jh->b_next_transaction == | 1856 | J_ASSERT(jh->b_next_transaction == |
@@ -1858,6 +1870,7 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh) | |||
1858 | * i_size already for this truncate so recovery will not | 1870 | * i_size already for this truncate so recovery will not |
1859 | * expose the disk blocks we are discarding here.) */ | 1871 | * expose the disk blocks we are discarding here.) */ |
1860 | J_ASSERT_JH(jh, transaction == journal->j_running_transaction); | 1872 | J_ASSERT_JH(jh, transaction == journal->j_running_transaction); |
1873 | JBUFFER_TRACE(jh, "on running transaction"); | ||
1861 | may_free = __dispose_buffer(jh, transaction); | 1874 | may_free = __dispose_buffer(jh, transaction); |
1862 | } | 1875 | } |
1863 | 1876 | ||
diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c index b6cf2be845a1..c051a94c8a97 100644 --- a/fs/jbd2/transaction.c +++ b/fs/jbd2/transaction.c | |||
@@ -967,6 +967,13 @@ int jbd2_journal_dirty_data(handle_t *handle, struct buffer_head *bh) | |||
967 | */ | 967 | */ |
968 | jbd_lock_bh_state(bh); | 968 | jbd_lock_bh_state(bh); |
969 | spin_lock(&journal->j_list_lock); | 969 | spin_lock(&journal->j_list_lock); |
970 | |||
971 | /* Now that we have bh_state locked, are we really still mapped? */ | ||
972 | if (!buffer_mapped(bh)) { | ||
973 | JBUFFER_TRACE(jh, "unmapped buffer, bailing out"); | ||
974 | goto no_journal; | ||
975 | } | ||
976 | |||
970 | if (jh->b_transaction) { | 977 | if (jh->b_transaction) { |
971 | JBUFFER_TRACE(jh, "has transaction"); | 978 | JBUFFER_TRACE(jh, "has transaction"); |
972 | if (jh->b_transaction != handle->h_transaction) { | 979 | if (jh->b_transaction != handle->h_transaction) { |
@@ -1028,6 +1035,11 @@ int jbd2_journal_dirty_data(handle_t *handle, struct buffer_head *bh) | |||
1028 | sync_dirty_buffer(bh); | 1035 | sync_dirty_buffer(bh); |
1029 | jbd_lock_bh_state(bh); | 1036 | jbd_lock_bh_state(bh); |
1030 | spin_lock(&journal->j_list_lock); | 1037 | spin_lock(&journal->j_list_lock); |
1038 | /* Since we dropped the lock... */ | ||
1039 | if (!buffer_mapped(bh)) { | ||
1040 | JBUFFER_TRACE(jh, "buffer got unmapped"); | ||
1041 | goto no_journal; | ||
1042 | } | ||
1031 | /* The buffer may become locked again at any | 1043 | /* The buffer may become locked again at any |
1032 | time if it is redirtied */ | 1044 | time if it is redirtied */ |
1033 | } | 1045 | } |
@@ -1824,6 +1836,7 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh) | |||
1824 | } | 1836 | } |
1825 | } | 1837 | } |
1826 | } else if (transaction == journal->j_committing_transaction) { | 1838 | } else if (transaction == journal->j_committing_transaction) { |
1839 | JBUFFER_TRACE(jh, "on committing transaction"); | ||
1827 | if (jh->b_jlist == BJ_Locked) { | 1840 | if (jh->b_jlist == BJ_Locked) { |
1828 | /* | 1841 | /* |
1829 | * The buffer is on the committing transaction's locked | 1842 | * The buffer is on the committing transaction's locked |
@@ -1838,7 +1851,6 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh) | |||
1838 | * can remove it's next_transaction pointer from the | 1851 | * can remove it's next_transaction pointer from the |
1839 | * running transaction if that is set, but nothing | 1852 | * running transaction if that is set, but nothing |
1840 | * else. */ | 1853 | * else. */ |
1841 | JBUFFER_TRACE(jh, "on committing transaction"); | ||
1842 | set_buffer_freed(bh); | 1854 | set_buffer_freed(bh); |
1843 | if (jh->b_next_transaction) { | 1855 | if (jh->b_next_transaction) { |
1844 | J_ASSERT(jh->b_next_transaction == | 1856 | J_ASSERT(jh->b_next_transaction == |
@@ -1858,6 +1870,7 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh) | |||
1858 | * i_size already for this truncate so recovery will not | 1870 | * i_size already for this truncate so recovery will not |
1859 | * expose the disk blocks we are discarding here.) */ | 1871 | * expose the disk blocks we are discarding here.) */ |
1860 | J_ASSERT_JH(jh, transaction == journal->j_running_transaction); | 1872 | J_ASSERT_JH(jh, transaction == journal->j_running_transaction); |
1873 | JBUFFER_TRACE(jh, "on running transaction"); | ||
1861 | may_free = __dispose_buffer(jh, transaction); | 1874 | may_free = __dispose_buffer(jh, transaction); |
1862 | } | 1875 | } |
1863 | 1876 | ||
diff --git a/fs/jfs/file.c b/fs/jfs/file.c index 34181b8f5a0a..aa9132d04920 100644 --- a/fs/jfs/file.c +++ b/fs/jfs/file.c | |||
@@ -109,6 +109,8 @@ const struct file_operations jfs_file_operations = { | |||
109 | .aio_write = generic_file_aio_write, | 109 | .aio_write = generic_file_aio_write, |
110 | .mmap = generic_file_mmap, | 110 | .mmap = generic_file_mmap, |
111 | .sendfile = generic_file_sendfile, | 111 | .sendfile = generic_file_sendfile, |
112 | .splice_read = generic_file_splice_read, | ||
113 | .splice_write = generic_file_splice_write, | ||
112 | .fsync = jfs_fsync, | 114 | .fsync = jfs_fsync, |
113 | .release = jfs_release, | 115 | .release = jfs_release, |
114 | .ioctl = jfs_ioctl, | 116 | .ioctl = jfs_ioctl, |
diff --git a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c index 489a3d63002d..ee9b473b7b80 100644 --- a/fs/jfs/jfs_imap.c +++ b/fs/jfs/jfs_imap.c | |||
@@ -318,7 +318,7 @@ int diRead(struct inode *ip) | |||
318 | struct inomap *imap; | 318 | struct inomap *imap; |
319 | int block_offset; | 319 | int block_offset; |
320 | int inodes_left; | 320 | int inodes_left; |
321 | uint pageno; | 321 | unsigned long pageno; |
322 | int rel_inode; | 322 | int rel_inode; |
323 | 323 | ||
324 | jfs_info("diRead: ino = %ld", ip->i_ino); | 324 | jfs_info("diRead: ino = %ld", ip->i_ino); |
@@ -606,7 +606,7 @@ int diWrite(tid_t tid, struct inode *ip) | |||
606 | int block_offset; | 606 | int block_offset; |
607 | int inodes_left; | 607 | int inodes_left; |
608 | struct metapage *mp; | 608 | struct metapage *mp; |
609 | uint pageno; | 609 | unsigned long pageno; |
610 | int rel_inode; | 610 | int rel_inode; |
611 | int dioffset; | 611 | int dioffset; |
612 | struct inode *ipimap; | 612 | struct inode *ipimap; |
diff --git a/fs/jfs/xattr.c b/fs/jfs/xattr.c index 4c7985ebca92..b753ba216450 100644 --- a/fs/jfs/xattr.c +++ b/fs/jfs/xattr.c | |||
@@ -756,6 +756,11 @@ static int can_set_system_xattr(struct inode *inode, const char *name, | |||
756 | return -EOPNOTSUPP; | 756 | return -EOPNOTSUPP; |
757 | } | 757 | } |
758 | 758 | ||
759 | /* | ||
760 | * Most of the permission checking is done by xattr_permission in the vfs. | ||
761 | * The local file system is responsible for handling the system.* namespace. | ||
762 | * We also need to verify that this is a namespace that we recognize. | ||
763 | */ | ||
759 | static int can_set_xattr(struct inode *inode, const char *name, | 764 | static int can_set_xattr(struct inode *inode, const char *name, |
760 | const void *value, size_t value_len) | 765 | const void *value, size_t value_len) |
761 | { | 766 | { |
@@ -771,10 +776,6 @@ static int can_set_xattr(struct inode *inode, const char *name, | |||
771 | strncmp(name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN)) | 776 | strncmp(name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN)) |
772 | return -EOPNOTSUPP; | 777 | return -EOPNOTSUPP; |
773 | 778 | ||
774 | if (!S_ISREG(inode->i_mode) && | ||
775 | (!S_ISDIR(inode->i_mode) || inode->i_mode &S_ISVTX)) | ||
776 | return -EPERM; | ||
777 | |||
778 | return 0; | 779 | return 0; |
779 | } | 780 | } |
780 | 781 | ||
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c index 634139232aaf..8ca18085e68d 100644 --- a/fs/lockd/svc.c +++ b/fs/lockd/svc.c | |||
@@ -353,9 +353,6 @@ EXPORT_SYMBOL(lockd_down); | |||
353 | * Sysctl parameters (same as module parameters, different interface). | 353 | * Sysctl parameters (same as module parameters, different interface). |
354 | */ | 354 | */ |
355 | 355 | ||
356 | /* Something that isn't CTL_ANY, CTL_NONE or a value that may clash. */ | ||
357 | #define CTL_UNNUMBERED -2 | ||
358 | |||
359 | static ctl_table nlm_sysctls[] = { | 356 | static ctl_table nlm_sysctls[] = { |
360 | { | 357 | { |
361 | .ctl_name = CTL_UNNUMBERED, | 358 | .ctl_name = CTL_UNNUMBERED, |
diff --git a/fs/msdos/namei.c b/fs/msdos/namei.c index b0f01b3b0536..452461955cbd 100644 --- a/fs/msdos/namei.c +++ b/fs/msdos/namei.c | |||
@@ -654,6 +654,7 @@ static struct inode_operations msdos_dir_inode_operations = { | |||
654 | .rmdir = msdos_rmdir, | 654 | .rmdir = msdos_rmdir, |
655 | .rename = msdos_rename, | 655 | .rename = msdos_rename, |
656 | .setattr = fat_notify_change, | 656 | .setattr = fat_notify_change, |
657 | .getattr = fat_getattr, | ||
657 | }; | 658 | }; |
658 | 659 | ||
659 | static int msdos_fill_super(struct super_block *sb, void *data, int silent) | 660 | static int msdos_fill_super(struct super_block *sb, void *data, int silent) |
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 4133ef5264e5..b34cd16f472f 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
@@ -935,8 +935,17 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru | |||
935 | 935 | ||
936 | no_entry: | 936 | no_entry: |
937 | res = d_materialise_unique(dentry, inode); | 937 | res = d_materialise_unique(dentry, inode); |
938 | if (res != NULL) | 938 | if (res != NULL) { |
939 | struct dentry *parent; | ||
940 | if (IS_ERR(res)) | ||
941 | goto out_unlock; | ||
942 | /* Was a directory renamed! */ | ||
943 | parent = dget_parent(res); | ||
944 | if (!IS_ROOT(parent)) | ||
945 | nfs_mark_for_revalidate(parent->d_inode); | ||
946 | dput(parent); | ||
939 | dentry = res; | 947 | dentry = res; |
948 | } | ||
940 | nfs_renew_times(dentry); | 949 | nfs_renew_times(dentry); |
941 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | 950 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); |
942 | out_unlock: | 951 | out_unlock: |
@@ -1132,6 +1141,8 @@ static struct dentry *nfs_readdir_lookup(nfs_readdir_descriptor_t *desc) | |||
1132 | alias = d_materialise_unique(dentry, inode); | 1141 | alias = d_materialise_unique(dentry, inode); |
1133 | if (alias != NULL) { | 1142 | if (alias != NULL) { |
1134 | dput(dentry); | 1143 | dput(dentry); |
1144 | if (IS_ERR(alias)) | ||
1145 | return NULL; | ||
1135 | dentry = alias; | 1146 | dentry = alias; |
1136 | } | 1147 | } |
1137 | 1148 | ||
diff --git a/fs/nfs/sysctl.c b/fs/nfs/sysctl.c index 2fe3403c2409..3ea50ac64820 100644 --- a/fs/nfs/sysctl.c +++ b/fs/nfs/sysctl.c | |||
@@ -18,11 +18,6 @@ | |||
18 | static const int nfs_set_port_min = 0; | 18 | static const int nfs_set_port_min = 0; |
19 | static const int nfs_set_port_max = 65535; | 19 | static const int nfs_set_port_max = 65535; |
20 | static struct ctl_table_header *nfs_callback_sysctl_table; | 20 | static struct ctl_table_header *nfs_callback_sysctl_table; |
21 | /* | ||
22 | * Something that isn't CTL_ANY, CTL_NONE or a value that may clash. | ||
23 | * Use the same values as fs/lockd/svc.c | ||
24 | */ | ||
25 | #define CTL_UNNUMBERED -2 | ||
26 | 21 | ||
27 | static ctl_table nfs_cb_sysctls[] = { | 22 | static ctl_table nfs_cb_sysctls[] = { |
28 | #ifdef CONFIG_NFS_V4 | 23 | #ifdef CONFIG_NFS_V4 |
diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c index 64db601c2bd2..7f5bad0393b1 100644 --- a/fs/nfsd/nfs3proc.c +++ b/fs/nfsd/nfs3proc.c | |||
@@ -258,7 +258,7 @@ nfsd3_proc_create(struct svc_rqst *rqstp, struct nfsd3_createargs *argp, | |||
258 | /* Now create the file and set attributes */ | 258 | /* Now create the file and set attributes */ |
259 | nfserr = nfsd_create_v3(rqstp, dirfhp, argp->name, argp->len, | 259 | nfserr = nfsd_create_v3(rqstp, dirfhp, argp->name, argp->len, |
260 | attr, newfhp, | 260 | attr, newfhp, |
261 | argp->createmode, argp->verf, NULL); | 261 | argp->createmode, argp->verf, NULL, NULL); |
262 | 262 | ||
263 | RETURN_STATUS(nfserr); | 263 | RETURN_STATUS(nfserr); |
264 | } | 264 | } |
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index 0a7bbdc4a10a..50bc94243ca1 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c | |||
@@ -93,6 +93,7 @@ do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_o | |||
93 | { | 93 | { |
94 | struct svc_fh resfh; | 94 | struct svc_fh resfh; |
95 | __be32 status; | 95 | __be32 status; |
96 | int created = 0; | ||
96 | 97 | ||
97 | fh_init(&resfh, NFS4_FHSIZE); | 98 | fh_init(&resfh, NFS4_FHSIZE); |
98 | open->op_truncate = 0; | 99 | open->op_truncate = 0; |
@@ -105,28 +106,27 @@ do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_o | |||
105 | status = nfsd_create_v3(rqstp, current_fh, open->op_fname.data, | 106 | status = nfsd_create_v3(rqstp, current_fh, open->op_fname.data, |
106 | open->op_fname.len, &open->op_iattr, | 107 | open->op_fname.len, &open->op_iattr, |
107 | &resfh, open->op_createmode, | 108 | &resfh, open->op_createmode, |
108 | (u32 *)open->op_verf.data, &open->op_truncate); | 109 | (u32 *)open->op_verf.data, &open->op_truncate, &created); |
109 | } | 110 | } else { |
110 | else { | ||
111 | status = nfsd_lookup(rqstp, current_fh, | 111 | status = nfsd_lookup(rqstp, current_fh, |
112 | open->op_fname.data, open->op_fname.len, &resfh); | 112 | open->op_fname.data, open->op_fname.len, &resfh); |
113 | fh_unlock(current_fh); | 113 | fh_unlock(current_fh); |
114 | } | 114 | } |
115 | if (status) | ||
116 | goto out; | ||
115 | 117 | ||
116 | if (!status) { | 118 | set_change_info(&open->op_cinfo, current_fh); |
117 | set_change_info(&open->op_cinfo, current_fh); | ||
118 | 119 | ||
119 | /* set reply cache */ | 120 | /* set reply cache */ |
120 | fh_dup2(current_fh, &resfh); | 121 | fh_dup2(current_fh, &resfh); |
121 | open->op_stateowner->so_replay.rp_openfh_len = | 122 | open->op_stateowner->so_replay.rp_openfh_len = resfh.fh_handle.fh_size; |
122 | resfh.fh_handle.fh_size; | 123 | memcpy(open->op_stateowner->so_replay.rp_openfh, |
123 | memcpy(open->op_stateowner->so_replay.rp_openfh, | 124 | &resfh.fh_handle.fh_base, resfh.fh_handle.fh_size); |
124 | &resfh.fh_handle.fh_base, | ||
125 | resfh.fh_handle.fh_size); | ||
126 | 125 | ||
126 | if (!created) | ||
127 | status = do_open_permission(rqstp, current_fh, open, MAY_NOP); | 127 | status = do_open_permission(rqstp, current_fh, open, MAY_NOP); |
128 | } | ||
129 | 128 | ||
129 | out: | ||
130 | fh_put(&resfh); | 130 | fh_put(&resfh); |
131 | return status; | 131 | return status; |
132 | } | 132 | } |
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c index e9d07704680e..81b8565d3837 100644 --- a/fs/nfsd/nfs4recover.c +++ b/fs/nfsd/nfs4recover.c | |||
@@ -274,7 +274,7 @@ nfsd4_clear_clid_dir(struct dentry *dir, struct dentry *dentry) | |||
274 | * any regular files anyway, just in case the directory was created by | 274 | * any regular files anyway, just in case the directory was created by |
275 | * a kernel from the future.... */ | 275 | * a kernel from the future.... */ |
276 | nfsd4_list_rec_dir(dentry, nfsd4_remove_clid_file); | 276 | nfsd4_list_rec_dir(dentry, nfsd4_remove_clid_file); |
277 | mutex_lock(&dir->d_inode->i_mutex); | 277 | mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT); |
278 | status = vfs_rmdir(dir->d_inode, dentry); | 278 | status = vfs_rmdir(dir->d_inode, dentry); |
279 | mutex_unlock(&dir->d_inode->i_mutex); | 279 | mutex_unlock(&dir->d_inode->i_mutex); |
280 | return status; | 280 | return status; |
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index f21e917bb8ed..bb4d926e4487 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
@@ -1177,7 +1177,7 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
1177 | /* | 1177 | /* |
1178 | * Get the dir op function pointer. | 1178 | * Get the dir op function pointer. |
1179 | */ | 1179 | */ |
1180 | err = nfserr_perm; | 1180 | err = 0; |
1181 | switch (type) { | 1181 | switch (type) { |
1182 | case S_IFREG: | 1182 | case S_IFREG: |
1183 | host_err = vfs_create(dirp, dchild, iap->ia_mode, NULL); | 1183 | host_err = vfs_create(dirp, dchild, iap->ia_mode, NULL); |
@@ -1237,7 +1237,7 @@ __be32 | |||
1237 | nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp, | 1237 | nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp, |
1238 | char *fname, int flen, struct iattr *iap, | 1238 | char *fname, int flen, struct iattr *iap, |
1239 | struct svc_fh *resfhp, int createmode, u32 *verifier, | 1239 | struct svc_fh *resfhp, int createmode, u32 *verifier, |
1240 | int *truncp) | 1240 | int *truncp, int *created) |
1241 | { | 1241 | { |
1242 | struct dentry *dentry, *dchild = NULL; | 1242 | struct dentry *dentry, *dchild = NULL; |
1243 | struct inode *dirp; | 1243 | struct inode *dirp; |
@@ -1331,6 +1331,8 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
1331 | host_err = vfs_create(dirp, dchild, iap->ia_mode, NULL); | 1331 | host_err = vfs_create(dirp, dchild, iap->ia_mode, NULL); |
1332 | if (host_err < 0) | 1332 | if (host_err < 0) |
1333 | goto out_nfserr; | 1333 | goto out_nfserr; |
1334 | if (created) | ||
1335 | *created = 1; | ||
1334 | 1336 | ||
1335 | if (EX_ISSYNC(fhp->fh_export)) { | 1337 | if (EX_ISSYNC(fhp->fh_export)) { |
1336 | err = nfserrno(nfsd_sync_dir(dentry)); | 1338 | err = nfserrno(nfsd_sync_dir(dentry)); |
diff --git a/fs/proc/base.c b/fs/proc/base.c index 8df27401d292..795319c54f72 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
@@ -442,7 +442,8 @@ static int mountstats_open(struct inode *inode, struct file *file) | |||
442 | 442 | ||
443 | if (task) { | 443 | if (task) { |
444 | task_lock(task); | 444 | task_lock(task); |
445 | namespace = task->nsproxy->namespace; | 445 | if (task->nsproxy) |
446 | namespace = task->nsproxy->namespace; | ||
446 | if (namespace) | 447 | if (namespace) |
447 | get_namespace(namespace); | 448 | get_namespace(namespace); |
448 | task_unlock(task); | 449 | task_unlock(task); |
diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c index b67ce9354048..ac14318c81ba 100644 --- a/fs/reiserfs/file.c +++ b/fs/reiserfs/file.c | |||
@@ -74,7 +74,8 @@ static int reiserfs_file_release(struct inode *inode, struct file *filp) | |||
74 | igrab(inode); | 74 | igrab(inode); |
75 | reiserfs_warning(inode->i_sb, | 75 | reiserfs_warning(inode->i_sb, |
76 | "pinning inode %lu because the " | 76 | "pinning inode %lu because the " |
77 | "preallocation can't be freed"); | 77 | "preallocation can't be freed", |
78 | inode->i_ino); | ||
78 | goto out; | 79 | goto out; |
79 | } | 80 | } |
80 | } | 81 | } |
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index 9041802df832..17249994110f 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c | |||
@@ -1619,6 +1619,7 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent) | |||
1619 | "jmacd-8: reiserfs_fill_super: unable to read bitmap"); | 1619 | "jmacd-8: reiserfs_fill_super: unable to read bitmap"); |
1620 | goto error; | 1620 | goto error; |
1621 | } | 1621 | } |
1622 | errval = -EINVAL; | ||
1622 | #ifdef CONFIG_REISERFS_CHECK | 1623 | #ifdef CONFIG_REISERFS_CHECK |
1623 | SWARN(silent, s, "CONFIG_REISERFS_CHECK is set ON"); | 1624 | SWARN(silent, s, "CONFIG_REISERFS_CHECK is set ON"); |
1624 | SWARN(silent, s, "- it is slow mode for debugging."); | 1625 | SWARN(silent, s, "- it is slow mode for debugging."); |
diff --git a/fs/splice.c b/fs/splice.c index a567010b62ac..da74583a00ee 100644 --- a/fs/splice.c +++ b/fs/splice.c | |||
@@ -74,7 +74,7 @@ static int page_cache_pipe_buf_steal(struct pipe_inode_info *pipe, | |||
74 | wait_on_page_writeback(page); | 74 | wait_on_page_writeback(page); |
75 | 75 | ||
76 | if (PagePrivate(page)) | 76 | if (PagePrivate(page)) |
77 | try_to_release_page(page, mapping_gfp_mask(mapping)); | 77 | try_to_release_page(page, GFP_KERNEL); |
78 | 78 | ||
79 | /* | 79 | /* |
80 | * If we succeeded in removing the mapping, set LRU flag | 80 | * If we succeeded in removing the mapping, set LRU flag |
@@ -333,7 +333,7 @@ __generic_file_splice_read(struct file *in, loff_t *ppos, | |||
333 | break; | 333 | break; |
334 | 334 | ||
335 | error = add_to_page_cache_lru(page, mapping, index, | 335 | error = add_to_page_cache_lru(page, mapping, index, |
336 | mapping_gfp_mask(mapping)); | 336 | GFP_KERNEL); |
337 | if (unlikely(error)) { | 337 | if (unlikely(error)) { |
338 | page_cache_release(page); | 338 | page_cache_release(page); |
339 | if (error == -EEXIST) | 339 | if (error == -EEXIST) |
@@ -557,7 +557,6 @@ static int pipe_to_file(struct pipe_inode_info *pipe, struct pipe_buffer *buf, | |||
557 | { | 557 | { |
558 | struct file *file = sd->file; | 558 | struct file *file = sd->file; |
559 | struct address_space *mapping = file->f_mapping; | 559 | struct address_space *mapping = file->f_mapping; |
560 | gfp_t gfp_mask = mapping_gfp_mask(mapping); | ||
561 | unsigned int offset, this_len; | 560 | unsigned int offset, this_len; |
562 | struct page *page; | 561 | struct page *page; |
563 | pgoff_t index; | 562 | pgoff_t index; |
@@ -591,7 +590,7 @@ static int pipe_to_file(struct pipe_inode_info *pipe, struct pipe_buffer *buf, | |||
591 | goto find_page; | 590 | goto find_page; |
592 | 591 | ||
593 | page = buf->page; | 592 | page = buf->page; |
594 | if (add_to_page_cache(page, mapping, index, gfp_mask)) { | 593 | if (add_to_page_cache(page, mapping, index, GFP_KERNEL)) { |
595 | unlock_page(page); | 594 | unlock_page(page); |
596 | goto find_page; | 595 | goto find_page; |
597 | } | 596 | } |
@@ -613,7 +612,7 @@ find_page: | |||
613 | * This will also lock the page | 612 | * This will also lock the page |
614 | */ | 613 | */ |
615 | ret = add_to_page_cache_lru(page, mapping, index, | 614 | ret = add_to_page_cache_lru(page, mapping, index, |
616 | gfp_mask); | 615 | GFP_KERNEL); |
617 | if (unlikely(ret)) | 616 | if (unlikely(ret)) |
618 | goto out; | 617 | goto out; |
619 | } | 618 | } |
@@ -707,9 +706,9 @@ out_ret: | |||
707 | * key here is the 'actor' worker passed in that actually moves the data | 706 | * key here is the 'actor' worker passed in that actually moves the data |
708 | * to the wanted destination. See pipe_to_file/pipe_to_sendpage above. | 707 | * to the wanted destination. See pipe_to_file/pipe_to_sendpage above. |
709 | */ | 708 | */ |
710 | ssize_t splice_from_pipe(struct pipe_inode_info *pipe, struct file *out, | 709 | static ssize_t __splice_from_pipe(struct pipe_inode_info *pipe, |
711 | loff_t *ppos, size_t len, unsigned int flags, | 710 | struct file *out, loff_t *ppos, size_t len, |
712 | splice_actor *actor) | 711 | unsigned int flags, splice_actor *actor) |
713 | { | 712 | { |
714 | int ret, do_wakeup, err; | 713 | int ret, do_wakeup, err; |
715 | struct splice_desc sd; | 714 | struct splice_desc sd; |
@@ -722,9 +721,6 @@ ssize_t splice_from_pipe(struct pipe_inode_info *pipe, struct file *out, | |||
722 | sd.file = out; | 721 | sd.file = out; |
723 | sd.pos = *ppos; | 722 | sd.pos = *ppos; |
724 | 723 | ||
725 | if (pipe->inode) | ||
726 | mutex_lock(&pipe->inode->i_mutex); | ||
727 | |||
728 | for (;;) { | 724 | for (;;) { |
729 | if (pipe->nrbufs) { | 725 | if (pipe->nrbufs) { |
730 | struct pipe_buffer *buf = pipe->bufs + pipe->curbuf; | 726 | struct pipe_buffer *buf = pipe->bufs + pipe->curbuf; |
@@ -797,9 +793,6 @@ ssize_t splice_from_pipe(struct pipe_inode_info *pipe, struct file *out, | |||
797 | pipe_wait(pipe); | 793 | pipe_wait(pipe); |
798 | } | 794 | } |
799 | 795 | ||
800 | if (pipe->inode) | ||
801 | mutex_unlock(&pipe->inode->i_mutex); | ||
802 | |||
803 | if (do_wakeup) { | 796 | if (do_wakeup) { |
804 | smp_mb(); | 797 | smp_mb(); |
805 | if (waitqueue_active(&pipe->wait)) | 798 | if (waitqueue_active(&pipe->wait)) |
@@ -810,6 +803,73 @@ ssize_t splice_from_pipe(struct pipe_inode_info *pipe, struct file *out, | |||
810 | return ret; | 803 | return ret; |
811 | } | 804 | } |
812 | 805 | ||
806 | ssize_t splice_from_pipe(struct pipe_inode_info *pipe, struct file *out, | ||
807 | loff_t *ppos, size_t len, unsigned int flags, | ||
808 | splice_actor *actor) | ||
809 | { | ||
810 | ssize_t ret; | ||
811 | struct inode *inode = out->f_mapping->host; | ||
812 | |||
813 | /* | ||
814 | * The actor worker might be calling ->prepare_write and | ||
815 | * ->commit_write. Most of the time, these expect i_mutex to | ||
816 | * be held. Since this may result in an ABBA deadlock with | ||
817 | * pipe->inode, we have to order lock acquiry here. | ||
818 | */ | ||
819 | inode_double_lock(inode, pipe->inode); | ||
820 | ret = __splice_from_pipe(pipe, out, ppos, len, flags, actor); | ||
821 | inode_double_unlock(inode, pipe->inode); | ||
822 | |||
823 | return ret; | ||
824 | } | ||
825 | |||
826 | /** | ||
827 | * generic_file_splice_write_nolock - generic_file_splice_write without mutexes | ||
828 | * @pipe: pipe info | ||
829 | * @out: file to write to | ||
830 | * @len: number of bytes to splice | ||
831 | * @flags: splice modifier flags | ||
832 | * | ||
833 | * Will either move or copy pages (determined by @flags options) from | ||
834 | * the given pipe inode to the given file. The caller is responsible | ||
835 | * for acquiring i_mutex on both inodes. | ||
836 | * | ||
837 | */ | ||
838 | ssize_t | ||
839 | generic_file_splice_write_nolock(struct pipe_inode_info *pipe, struct file *out, | ||
840 | loff_t *ppos, size_t len, unsigned int flags) | ||
841 | { | ||
842 | struct address_space *mapping = out->f_mapping; | ||
843 | struct inode *inode = mapping->host; | ||
844 | ssize_t ret; | ||
845 | int err; | ||
846 | |||
847 | err = remove_suid(out->f_dentry); | ||
848 | if (unlikely(err)) | ||
849 | return err; | ||
850 | |||
851 | ret = __splice_from_pipe(pipe, out, ppos, len, flags, pipe_to_file); | ||
852 | if (ret > 0) { | ||
853 | *ppos += ret; | ||
854 | |||
855 | /* | ||
856 | * If file or inode is SYNC and we actually wrote some data, | ||
857 | * sync it. | ||
858 | */ | ||
859 | if (unlikely((out->f_flags & O_SYNC) || IS_SYNC(inode))) { | ||
860 | err = generic_osync_inode(inode, mapping, | ||
861 | OSYNC_METADATA|OSYNC_DATA); | ||
862 | |||
863 | if (err) | ||
864 | ret = err; | ||
865 | } | ||
866 | } | ||
867 | |||
868 | return ret; | ||
869 | } | ||
870 | |||
871 | EXPORT_SYMBOL(generic_file_splice_write_nolock); | ||
872 | |||
813 | /** | 873 | /** |
814 | * generic_file_splice_write - splice data from a pipe to a file | 874 | * generic_file_splice_write - splice data from a pipe to a file |
815 | * @pipe: pipe info | 875 | * @pipe: pipe info |
@@ -826,12 +886,21 @@ generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out, | |||
826 | loff_t *ppos, size_t len, unsigned int flags) | 886 | loff_t *ppos, size_t len, unsigned int flags) |
827 | { | 887 | { |
828 | struct address_space *mapping = out->f_mapping; | 888 | struct address_space *mapping = out->f_mapping; |
889 | struct inode *inode = mapping->host; | ||
829 | ssize_t ret; | 890 | ssize_t ret; |
891 | int err; | ||
892 | |||
893 | err = should_remove_suid(out->f_dentry); | ||
894 | if (unlikely(err)) { | ||
895 | mutex_lock(&inode->i_mutex); | ||
896 | err = __remove_suid(out->f_dentry, err); | ||
897 | mutex_unlock(&inode->i_mutex); | ||
898 | if (err) | ||
899 | return err; | ||
900 | } | ||
830 | 901 | ||
831 | ret = splice_from_pipe(pipe, out, ppos, len, flags, pipe_to_file); | 902 | ret = splice_from_pipe(pipe, out, ppos, len, flags, pipe_to_file); |
832 | if (ret > 0) { | 903 | if (ret > 0) { |
833 | struct inode *inode = mapping->host; | ||
834 | |||
835 | *ppos += ret; | 904 | *ppos += ret; |
836 | 905 | ||
837 | /* | 906 | /* |
@@ -839,8 +908,6 @@ generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out, | |||
839 | * sync it. | 908 | * sync it. |
840 | */ | 909 | */ |
841 | if (unlikely((out->f_flags & O_SYNC) || IS_SYNC(inode))) { | 910 | if (unlikely((out->f_flags & O_SYNC) || IS_SYNC(inode))) { |
842 | int err; | ||
843 | |||
844 | mutex_lock(&inode->i_mutex); | 911 | mutex_lock(&inode->i_mutex); |
845 | err = generic_osync_inode(inode, mapping, | 912 | err = generic_osync_inode(inode, mapping, |
846 | OSYNC_METADATA|OSYNC_DATA); | 913 | OSYNC_METADATA|OSYNC_DATA); |
@@ -1042,6 +1109,19 @@ out_release: | |||
1042 | EXPORT_SYMBOL(do_splice_direct); | 1109 | EXPORT_SYMBOL(do_splice_direct); |
1043 | 1110 | ||
1044 | /* | 1111 | /* |
1112 | * After the inode slimming patch, i_pipe/i_bdev/i_cdev share the same | ||
1113 | * location, so checking ->i_pipe is not enough to verify that this is a | ||
1114 | * pipe. | ||
1115 | */ | ||
1116 | static inline struct pipe_inode_info *pipe_info(struct inode *inode) | ||
1117 | { | ||
1118 | if (S_ISFIFO(inode->i_mode)) | ||
1119 | return inode->i_pipe; | ||
1120 | |||
1121 | return NULL; | ||
1122 | } | ||
1123 | |||
1124 | /* | ||
1045 | * Determine where to splice to/from. | 1125 | * Determine where to splice to/from. |
1046 | */ | 1126 | */ |
1047 | static long do_splice(struct file *in, loff_t __user *off_in, | 1127 | static long do_splice(struct file *in, loff_t __user *off_in, |
@@ -1052,7 +1132,7 @@ static long do_splice(struct file *in, loff_t __user *off_in, | |||
1052 | loff_t offset, *off; | 1132 | loff_t offset, *off; |
1053 | long ret; | 1133 | long ret; |
1054 | 1134 | ||
1055 | pipe = in->f_dentry->d_inode->i_pipe; | 1135 | pipe = pipe_info(in->f_dentry->d_inode); |
1056 | if (pipe) { | 1136 | if (pipe) { |
1057 | if (off_in) | 1137 | if (off_in) |
1058 | return -ESPIPE; | 1138 | return -ESPIPE; |
@@ -1073,7 +1153,7 @@ static long do_splice(struct file *in, loff_t __user *off_in, | |||
1073 | return ret; | 1153 | return ret; |
1074 | } | 1154 | } |
1075 | 1155 | ||
1076 | pipe = out->f_dentry->d_inode->i_pipe; | 1156 | pipe = pipe_info(out->f_dentry->d_inode); |
1077 | if (pipe) { | 1157 | if (pipe) { |
1078 | if (off_out) | 1158 | if (off_out) |
1079 | return -ESPIPE; | 1159 | return -ESPIPE; |
@@ -1231,7 +1311,7 @@ static int get_iovec_page_array(const struct iovec __user *iov, | |||
1231 | static long do_vmsplice(struct file *file, const struct iovec __user *iov, | 1311 | static long do_vmsplice(struct file *file, const struct iovec __user *iov, |
1232 | unsigned long nr_segs, unsigned int flags) | 1312 | unsigned long nr_segs, unsigned int flags) |
1233 | { | 1313 | { |
1234 | struct pipe_inode_info *pipe = file->f_dentry->d_inode->i_pipe; | 1314 | struct pipe_inode_info *pipe; |
1235 | struct page *pages[PIPE_BUFFERS]; | 1315 | struct page *pages[PIPE_BUFFERS]; |
1236 | struct partial_page partial[PIPE_BUFFERS]; | 1316 | struct partial_page partial[PIPE_BUFFERS]; |
1237 | struct splice_pipe_desc spd = { | 1317 | struct splice_pipe_desc spd = { |
@@ -1241,7 +1321,8 @@ static long do_vmsplice(struct file *file, const struct iovec __user *iov, | |||
1241 | .ops = &user_page_pipe_buf_ops, | 1321 | .ops = &user_page_pipe_buf_ops, |
1242 | }; | 1322 | }; |
1243 | 1323 | ||
1244 | if (unlikely(!pipe)) | 1324 | pipe = pipe_info(file->f_dentry->d_inode); |
1325 | if (!pipe) | ||
1245 | return -EBADF; | 1326 | return -EBADF; |
1246 | if (unlikely(nr_segs > UIO_MAXIOV)) | 1327 | if (unlikely(nr_segs > UIO_MAXIOV)) |
1247 | return -EINVAL; | 1328 | return -EINVAL; |
@@ -1400,13 +1481,7 @@ static int link_pipe(struct pipe_inode_info *ipipe, | |||
1400 | * grabbing by inode address. Otherwise two different processes | 1481 | * grabbing by inode address. Otherwise two different processes |
1401 | * could deadlock (one doing tee from A -> B, the other from B -> A). | 1482 | * could deadlock (one doing tee from A -> B, the other from B -> A). |
1402 | */ | 1483 | */ |
1403 | if (ipipe->inode < opipe->inode) { | 1484 | inode_double_lock(ipipe->inode, opipe->inode); |
1404 | mutex_lock_nested(&ipipe->inode->i_mutex, I_MUTEX_PARENT); | ||
1405 | mutex_lock_nested(&opipe->inode->i_mutex, I_MUTEX_CHILD); | ||
1406 | } else { | ||
1407 | mutex_lock_nested(&opipe->inode->i_mutex, I_MUTEX_PARENT); | ||
1408 | mutex_lock_nested(&ipipe->inode->i_mutex, I_MUTEX_CHILD); | ||
1409 | } | ||
1410 | 1485 | ||
1411 | do { | 1486 | do { |
1412 | if (!opipe->readers) { | 1487 | if (!opipe->readers) { |
@@ -1450,8 +1525,7 @@ static int link_pipe(struct pipe_inode_info *ipipe, | |||
1450 | i++; | 1525 | i++; |
1451 | } while (len); | 1526 | } while (len); |
1452 | 1527 | ||
1453 | mutex_unlock(&ipipe->inode->i_mutex); | 1528 | inode_double_unlock(ipipe->inode, opipe->inode); |
1454 | mutex_unlock(&opipe->inode->i_mutex); | ||
1455 | 1529 | ||
1456 | /* | 1530 | /* |
1457 | * If we put data in the output pipe, wakeup any potential readers. | 1531 | * If we put data in the output pipe, wakeup any potential readers. |
@@ -1475,8 +1549,8 @@ static int link_pipe(struct pipe_inode_info *ipipe, | |||
1475 | static long do_tee(struct file *in, struct file *out, size_t len, | 1549 | static long do_tee(struct file *in, struct file *out, size_t len, |
1476 | unsigned int flags) | 1550 | unsigned int flags) |
1477 | { | 1551 | { |
1478 | struct pipe_inode_info *ipipe = in->f_dentry->d_inode->i_pipe; | 1552 | struct pipe_inode_info *ipipe = pipe_info(in->f_dentry->d_inode); |
1479 | struct pipe_inode_info *opipe = out->f_dentry->d_inode->i_pipe; | 1553 | struct pipe_inode_info *opipe = pipe_info(out->f_dentry->d_inode); |
1480 | int ret = -EINVAL; | 1554 | int ret = -EINVAL; |
1481 | 1555 | ||
1482 | /* | 1556 | /* |
diff --git a/fs/vfat/namei.c b/fs/vfat/namei.c index edb711ff7b05..0afd745a37cd 100644 --- a/fs/vfat/namei.c +++ b/fs/vfat/namei.c | |||
@@ -1004,6 +1004,7 @@ static struct inode_operations vfat_dir_inode_operations = { | |||
1004 | .rmdir = vfat_rmdir, | 1004 | .rmdir = vfat_rmdir, |
1005 | .rename = vfat_rename, | 1005 | .rename = vfat_rename, |
1006 | .setattr = fat_notify_change, | 1006 | .setattr = fat_notify_change, |
1007 | .getattr = fat_getattr, | ||
1007 | }; | 1008 | }; |
1008 | 1009 | ||
1009 | static int vfat_fill_super(struct super_block *sb, void *data, int silent) | 1010 | static int vfat_fill_super(struct super_block *sb, void *data, int silent) |
diff --git a/fs/xattr.c b/fs/xattr.c index 395635100f77..0901bdc2ce24 100644 --- a/fs/xattr.c +++ b/fs/xattr.c | |||
@@ -48,14 +48,21 @@ xattr_permission(struct inode *inode, const char *name, int mask) | |||
48 | return 0; | 48 | return 0; |
49 | 49 | ||
50 | /* | 50 | /* |
51 | * The trusted.* namespace can only accessed by a privilegued user. | 51 | * The trusted.* namespace can only be accessed by a privileged user. |
52 | */ | 52 | */ |
53 | if (!strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN)) | 53 | if (!strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN)) |
54 | return (capable(CAP_SYS_ADMIN) ? 0 : -EPERM); | 54 | return (capable(CAP_SYS_ADMIN) ? 0 : -EPERM); |
55 | 55 | ||
56 | /* In user.* namespace, only regular files and directories can have | ||
57 | * extended attributes. For sticky directories, only the owner and | ||
58 | * privileged user can write attributes. | ||
59 | */ | ||
56 | if (!strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN)) { | 60 | if (!strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN)) { |
57 | if (!S_ISREG(inode->i_mode) && | 61 | if (!S_ISREG(inode->i_mode) && !S_ISDIR(inode->i_mode)) |
58 | (!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX)) | 62 | return -EPERM; |
63 | if (S_ISDIR(inode->i_mode) && (inode->i_mode & S_ISVTX) && | ||
64 | (mask & MAY_WRITE) && (current->fsuid != inode->i_uid) && | ||
65 | !capable(CAP_FOWNER)) | ||
59 | return -EPERM; | 66 | return -EPERM; |
60 | } | 67 | } |
61 | 68 | ||
diff --git a/fs/xfs/Makefile-linux-2.6 b/fs/xfs/Makefile-linux-2.6 index 291948d5085a..b49989bb89ad 100644 --- a/fs/xfs/Makefile-linux-2.6 +++ b/fs/xfs/Makefile-linux-2.6 | |||
@@ -21,22 +21,7 @@ EXTRA_CFLAGS += -Ifs/xfs -Ifs/xfs/linux-2.6 -funsigned-char | |||
21 | XFS_LINUX := linux-2.6 | 21 | XFS_LINUX := linux-2.6 |
22 | 22 | ||
23 | ifeq ($(CONFIG_XFS_DEBUG),y) | 23 | ifeq ($(CONFIG_XFS_DEBUG),y) |
24 | EXTRA_CFLAGS += -g -DSTATIC="" -DDEBUG | 24 | EXTRA_CFLAGS += -g |
25 | EXTRA_CFLAGS += -DXFS_BUF_LOCK_TRACKING | ||
26 | endif | ||
27 | ifeq ($(CONFIG_XFS_TRACE),y) | ||
28 | EXTRA_CFLAGS += -DXFS_ALLOC_TRACE | ||
29 | EXTRA_CFLAGS += -DXFS_ATTR_TRACE | ||
30 | EXTRA_CFLAGS += -DXFS_BLI_TRACE | ||
31 | EXTRA_CFLAGS += -DXFS_BMAP_TRACE | ||
32 | EXTRA_CFLAGS += -DXFS_BMBT_TRACE | ||
33 | EXTRA_CFLAGS += -DXFS_DIR2_TRACE | ||
34 | EXTRA_CFLAGS += -DXFS_DQUOT_TRACE | ||
35 | EXTRA_CFLAGS += -DXFS_ILOCK_TRACE | ||
36 | EXTRA_CFLAGS += -DXFS_LOG_TRACE | ||
37 | EXTRA_CFLAGS += -DXFS_RW_TRACE | ||
38 | EXTRA_CFLAGS += -DXFS_BUF_TRACE | ||
39 | EXTRA_CFLAGS += -DXFS_VNODE_TRACE | ||
40 | endif | 25 | endif |
41 | 26 | ||
42 | obj-$(CONFIG_XFS_FS) += xfs.o | 27 | obj-$(CONFIG_XFS_FS) += xfs.o |
diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c index db5f5a3608ca..d3382843698e 100644 --- a/fs/xfs/linux-2.6/xfs_buf.c +++ b/fs/xfs/linux-2.6/xfs_buf.c | |||
@@ -15,6 +15,7 @@ | |||
15 | * along with this program; if not, write the Free Software Foundation, | 15 | * along with this program; if not, write the Free Software Foundation, |
16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | 16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
17 | */ | 17 | */ |
18 | #include "xfs.h" | ||
18 | #include <linux/stddef.h> | 19 | #include <linux/stddef.h> |
19 | #include <linux/errno.h> | 20 | #include <linux/errno.h> |
20 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
@@ -31,7 +32,6 @@ | |||
31 | #include <linux/kthread.h> | 32 | #include <linux/kthread.h> |
32 | #include <linux/migrate.h> | 33 | #include <linux/migrate.h> |
33 | #include <linux/backing-dev.h> | 34 | #include <linux/backing-dev.h> |
34 | #include "xfs_linux.h" | ||
35 | 35 | ||
36 | STATIC kmem_zone_t *xfs_buf_zone; | 36 | STATIC kmem_zone_t *xfs_buf_zone; |
37 | STATIC kmem_shaker_t xfs_buf_shake; | 37 | STATIC kmem_shaker_t xfs_buf_shake; |
@@ -1406,7 +1406,7 @@ xfs_alloc_bufhash( | |||
1406 | btp->bt_hashshift = external ? 3 : 8; /* 8 or 256 buckets */ | 1406 | btp->bt_hashshift = external ? 3 : 8; /* 8 or 256 buckets */ |
1407 | btp->bt_hashmask = (1 << btp->bt_hashshift) - 1; | 1407 | btp->bt_hashmask = (1 << btp->bt_hashshift) - 1; |
1408 | btp->bt_hash = kmem_zalloc((1 << btp->bt_hashshift) * | 1408 | btp->bt_hash = kmem_zalloc((1 << btp->bt_hashshift) * |
1409 | sizeof(xfs_bufhash_t), KM_SLEEP); | 1409 | sizeof(xfs_bufhash_t), KM_SLEEP | KM_LARGE); |
1410 | for (i = 0; i < (1 << btp->bt_hashshift); i++) { | 1410 | for (i = 0; i < (1 << btp->bt_hashshift); i++) { |
1411 | spin_lock_init(&btp->bt_hash[i].bh_lock); | 1411 | spin_lock_init(&btp->bt_hash[i].bh_lock); |
1412 | INIT_LIST_HEAD(&btp->bt_hash[i].bh_list); | 1412 | INIT_LIST_HEAD(&btp->bt_hash[i].bh_list); |
diff --git a/fs/xfs/linux-2.6/xfs_dmapi_priv.h b/fs/xfs/linux-2.6/xfs_dmapi_priv.h new file mode 100644 index 000000000000..a8b0b1685eed --- /dev/null +++ b/fs/xfs/linux-2.6/xfs_dmapi_priv.h | |||
@@ -0,0 +1,28 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2000-2006 Silicon Graphics, Inc. | ||
3 | * All Rights Reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it would be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write the Free Software Foundation, | ||
16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
17 | */ | ||
18 | #ifndef __XFS_DMAPI_PRIV_H__ | ||
19 | #define __XFS_DMAPI_PRIV_H__ | ||
20 | |||
21 | /* | ||
22 | * Based on IO_ISDIRECT, decide which i_ flag is set. | ||
23 | */ | ||
24 | #define DM_SEM_FLAG_RD(ioflags) (((ioflags) & IO_ISDIRECT) ? \ | ||
25 | DM_FLAGS_IMUX : 0) | ||
26 | #define DM_SEM_FLAG_WR (DM_FLAGS_IALLOCSEM_WR | DM_FLAGS_IMUX) | ||
27 | |||
28 | #endif /*__XFS_DMAPI_PRIV_H__*/ | ||
diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c index a74f854d91e6..74d094829a4d 100644 --- a/fs/xfs/linux-2.6/xfs_ioctl.c +++ b/fs/xfs/linux-2.6/xfs_ioctl.c | |||
@@ -341,8 +341,11 @@ xfs_open_by_handle( | |||
341 | put_unused_fd(new_fd); | 341 | put_unused_fd(new_fd); |
342 | return -XFS_ERROR(-PTR_ERR(filp)); | 342 | return -XFS_ERROR(-PTR_ERR(filp)); |
343 | } | 343 | } |
344 | if (inode->i_mode & S_IFREG) | 344 | if (inode->i_mode & S_IFREG) { |
345 | /* invisible operation should not change atime */ | ||
346 | filp->f_flags |= O_NOATIME; | ||
345 | filp->f_op = &xfs_invis_file_operations; | 347 | filp->f_op = &xfs_invis_file_operations; |
348 | } | ||
346 | 349 | ||
347 | fd_install(new_fd, filp); | 350 | fd_install(new_fd, filp); |
348 | return new_fd; | 351 | return new_fd; |
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c index 38c4d128a8c0..de05abbbe7fd 100644 --- a/fs/xfs/linux-2.6/xfs_super.c +++ b/fs/xfs/linux-2.6/xfs_super.c | |||
@@ -227,9 +227,7 @@ xfs_initialize_vnode( | |||
227 | xfs_revalidate_inode(XFS_BHVTOM(bdp), vp, ip); | 227 | xfs_revalidate_inode(XFS_BHVTOM(bdp), vp, ip); |
228 | xfs_set_inodeops(inode); | 228 | xfs_set_inodeops(inode); |
229 | 229 | ||
230 | spin_lock(&ip->i_flags_lock); | 230 | xfs_iflags_clear(ip, XFS_INEW); |
231 | ip->i_flags &= ~XFS_INEW; | ||
232 | spin_unlock(&ip->i_flags_lock); | ||
233 | barrier(); | 231 | barrier(); |
234 | 232 | ||
235 | unlock_new_inode(inode); | 233 | unlock_new_inode(inode); |
diff --git a/fs/xfs/support/debug.c b/fs/xfs/support/debug.c index c75f68361e33..4363512d2f90 100644 --- a/fs/xfs/support/debug.c +++ b/fs/xfs/support/debug.c | |||
@@ -15,11 +15,9 @@ | |||
15 | * along with this program; if not, write the Free Software Foundation, | 15 | * along with this program; if not, write the Free Software Foundation, |
16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | 16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
17 | */ | 17 | */ |
18 | #include <xfs.h> | ||
18 | #include "debug.h" | 19 | #include "debug.h" |
19 | #include "spin.h" | 20 | #include "spin.h" |
20 | #include <asm/page.h> | ||
21 | #include <linux/sched.h> | ||
22 | #include <linux/kernel.h> | ||
23 | 21 | ||
24 | static char message[256]; /* keep it off the stack */ | 22 | static char message[256]; /* keep it off the stack */ |
25 | static DEFINE_SPINLOCK(xfs_err_lock); | 23 | static DEFINE_SPINLOCK(xfs_err_lock); |
diff --git a/fs/xfs/support/move.c b/fs/xfs/support/move.c index caefa17b80fe..ac8617ca3909 100644 --- a/fs/xfs/support/move.c +++ b/fs/xfs/support/move.c | |||
@@ -22,7 +22,7 @@ | |||
22 | * as we go. | 22 | * as we go. |
23 | */ | 23 | */ |
24 | int | 24 | int |
25 | uio_read(caddr_t src, size_t len, struct uio *uio) | 25 | xfs_uio_read(caddr_t src, size_t len, struct uio *uio) |
26 | { | 26 | { |
27 | size_t count; | 27 | size_t count; |
28 | 28 | ||
diff --git a/fs/xfs/support/move.h b/fs/xfs/support/move.h index 97a2498d2da3..977879c24ff5 100644 --- a/fs/xfs/support/move.h +++ b/fs/xfs/support/move.h | |||
@@ -65,6 +65,6 @@ struct uio { | |||
65 | typedef struct uio uio_t; | 65 | typedef struct uio uio_t; |
66 | typedef struct iovec iovec_t; | 66 | typedef struct iovec iovec_t; |
67 | 67 | ||
68 | extern int uio_read (caddr_t, size_t, uio_t *); | 68 | extern int xfs_uio_read (caddr_t, size_t, uio_t *); |
69 | 69 | ||
70 | #endif /* __XFS_SUPPORT_MOVE_H__ */ | 70 | #endif /* __XFS_SUPPORT_MOVE_H__ */ |
diff --git a/fs/xfs/xfs.h b/fs/xfs/xfs.h index 1a48dbb902a7..bf0a12040b13 100644 --- a/fs/xfs/xfs.h +++ b/fs/xfs/xfs.h | |||
@@ -17,5 +17,28 @@ | |||
17 | */ | 17 | */ |
18 | #ifndef __XFS_H__ | 18 | #ifndef __XFS_H__ |
19 | #define __XFS_H__ | 19 | #define __XFS_H__ |
20 | |||
21 | #ifdef CONFIG_XFS_DEBUG | ||
22 | #define STATIC | ||
23 | #define DEBUG 1 | ||
24 | #define XFS_BUF_LOCK_TRACKING 1 | ||
25 | /* #define QUOTADEBUG 1 */ | ||
26 | #endif | ||
27 | |||
28 | #ifdef CONFIG_XFS_TRACE | ||
29 | #define XFS_ALLOC_TRACE 1 | ||
30 | #define XFS_ATTR_TRACE 1 | ||
31 | #define XFS_BLI_TRACE 1 | ||
32 | #define XFS_BMAP_TRACE 1 | ||
33 | #define XFS_BMBT_TRACE 1 | ||
34 | #define XFS_DIR2_TRACE 1 | ||
35 | #define XFS_DQUOT_TRACE 1 | ||
36 | #define XFS_ILOCK_TRACE 1 | ||
37 | #define XFS_LOG_TRACE 1 | ||
38 | #define XFS_RW_TRACE 1 | ||
39 | #define XFS_BUF_TRACE 1 | ||
40 | #define XFS_VNODE_TRACE 1 | ||
41 | #endif | ||
42 | |||
20 | #include <linux-2.6/xfs_linux.h> | 43 | #include <linux-2.6/xfs_linux.h> |
21 | #endif /* __XFS_H__ */ | 44 | #endif /* __XFS_H__ */ |
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index 5b050c06795f..498ad50d1f45 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c | |||
@@ -1171,6 +1171,8 @@ xfs_bmap_add_extent_delay_real( | |||
1171 | xfs_bmap_trace_pre_update(fname, "0", ip, idx, XFS_DATA_FORK); | 1171 | xfs_bmap_trace_pre_update(fname, "0", ip, idx, XFS_DATA_FORK); |
1172 | xfs_bmbt_set_blockcount(ep, temp); | 1172 | xfs_bmbt_set_blockcount(ep, temp); |
1173 | r[0] = *new; | 1173 | r[0] = *new; |
1174 | r[1].br_state = PREV.br_state; | ||
1175 | r[1].br_startblock = 0; | ||
1174 | r[1].br_startoff = new_endoff; | 1176 | r[1].br_startoff = new_endoff; |
1175 | temp2 = PREV.br_startoff + PREV.br_blockcount - new_endoff; | 1177 | temp2 = PREV.br_startoff + PREV.br_blockcount - new_endoff; |
1176 | r[1].br_blockcount = temp2; | 1178 | r[1].br_blockcount = temp2; |
diff --git a/fs/xfs/xfs_dir2.c b/fs/xfs/xfs_dir2.c index 8edbe1adb95b..8e8e5279334a 100644 --- a/fs/xfs/xfs_dir2.c +++ b/fs/xfs/xfs_dir2.c | |||
@@ -678,7 +678,7 @@ xfs_dir2_put_dirent64_uio( | |||
678 | idbp->d_off = pa->cook; | 678 | idbp->d_off = pa->cook; |
679 | idbp->d_name[namelen] = '\0'; | 679 | idbp->d_name[namelen] = '\0'; |
680 | memcpy(idbp->d_name, pa->name, namelen); | 680 | memcpy(idbp->d_name, pa->name, namelen); |
681 | rval = uio_read((caddr_t)idbp, reclen, uio); | 681 | rval = xfs_uio_read((caddr_t)idbp, reclen, uio); |
682 | pa->done = (rval == 0); | 682 | pa->done = (rval == 0); |
683 | return rval; | 683 | return rval; |
684 | } | 684 | } |
diff --git a/fs/xfs/xfs_dmapi.h b/fs/xfs/xfs_dmapi.h index 4e7865ad6f0e..adc3d251240d 100644 --- a/fs/xfs/xfs_dmapi.h +++ b/fs/xfs/xfs_dmapi.h | |||
@@ -157,27 +157,9 @@ typedef enum { | |||
157 | #define DM_FLAGS_IALLOCSEM_WR 0x020 /* thread holds i_alloc_sem wr */ | 157 | #define DM_FLAGS_IALLOCSEM_WR 0x020 /* thread holds i_alloc_sem wr */ |
158 | 158 | ||
159 | /* | 159 | /* |
160 | * Based on IO_ISDIRECT, decide which i_ flag is set. | 160 | * Pull in platform specific event flags defines |
161 | */ | 161 | */ |
162 | #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) | 162 | #include "xfs_dmapi_priv.h" |
163 | #define DM_SEM_FLAG_RD(ioflags) (((ioflags) & IO_ISDIRECT) ? \ | ||
164 | DM_FLAGS_IMUX : 0) | ||
165 | #define DM_SEM_FLAG_WR (DM_FLAGS_IALLOCSEM_WR | DM_FLAGS_IMUX) | ||
166 | #endif | ||
167 | |||
168 | #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)) && \ | ||
169 | (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,22)) | ||
170 | #define DM_SEM_FLAG_RD(ioflags) (((ioflags) & IO_ISDIRECT) ? \ | ||
171 | DM_FLAGS_IALLOCSEM_RD : DM_FLAGS_IMUX) | ||
172 | #define DM_SEM_FLAG_WR (DM_FLAGS_IALLOCSEM_WR | DM_FLAGS_IMUX) | ||
173 | #endif | ||
174 | |||
175 | #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,21) | ||
176 | #define DM_SEM_FLAG_RD(ioflags) (((ioflags) & IO_ISDIRECT) ? \ | ||
177 | 0 : DM_FLAGS_IMUX) | ||
178 | #define DM_SEM_FLAG_WR (DM_FLAGS_IMUX) | ||
179 | #endif | ||
180 | |||
181 | 163 | ||
182 | /* | 164 | /* |
183 | * Macros to turn caller specified delay/block flags into | 165 | * Macros to turn caller specified delay/block flags into |
diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c index b73d216ecaf9..c1c89dac19cc 100644 --- a/fs/xfs/xfs_iget.c +++ b/fs/xfs/xfs_iget.c | |||
@@ -215,7 +215,7 @@ again: | |||
215 | * If INEW is set this inode is being set up | 215 | * If INEW is set this inode is being set up |
216 | * we need to pause and try again. | 216 | * we need to pause and try again. |
217 | */ | 217 | */ |
218 | if (ip->i_flags & XFS_INEW) { | 218 | if (xfs_iflags_test(ip, XFS_INEW)) { |
219 | read_unlock(&ih->ih_lock); | 219 | read_unlock(&ih->ih_lock); |
220 | delay(1); | 220 | delay(1); |
221 | XFS_STATS_INC(xs_ig_frecycle); | 221 | XFS_STATS_INC(xs_ig_frecycle); |
@@ -230,22 +230,50 @@ again: | |||
230 | * on its way out of the system, | 230 | * on its way out of the system, |
231 | * we need to pause and try again. | 231 | * we need to pause and try again. |
232 | */ | 232 | */ |
233 | if (ip->i_flags & XFS_IRECLAIM) { | 233 | if (xfs_iflags_test(ip, XFS_IRECLAIM)) { |
234 | read_unlock(&ih->ih_lock); | 234 | read_unlock(&ih->ih_lock); |
235 | delay(1); | 235 | delay(1); |
236 | XFS_STATS_INC(xs_ig_frecycle); | 236 | XFS_STATS_INC(xs_ig_frecycle); |
237 | 237 | ||
238 | goto again; | 238 | goto again; |
239 | } | 239 | } |
240 | ASSERT(xfs_iflags_test(ip, XFS_IRECLAIMABLE)); | ||
241 | |||
242 | /* | ||
243 | * If lookup is racing with unlink, then we | ||
244 | * should return an error immediately so we | ||
245 | * don't remove it from the reclaim list and | ||
246 | * potentially leak the inode. | ||
247 | */ | ||
248 | if ((ip->i_d.di_mode == 0) && | ||
249 | !(flags & XFS_IGET_CREATE)) { | ||
250 | read_unlock(&ih->ih_lock); | ||
251 | return ENOENT; | ||
252 | } | ||
253 | |||
254 | /* | ||
255 | * There may be transactions sitting in the | ||
256 | * incore log buffers or being flushed to disk | ||
257 | * at this time. We can't clear the | ||
258 | * XFS_IRECLAIMABLE flag until these | ||
259 | * transactions have hit the disk, otherwise we | ||
260 | * will void the guarantee the flag provides | ||
261 | * xfs_iunpin() | ||
262 | */ | ||
263 | if (xfs_ipincount(ip)) { | ||
264 | read_unlock(&ih->ih_lock); | ||
265 | xfs_log_force(mp, 0, | ||
266 | XFS_LOG_FORCE|XFS_LOG_SYNC); | ||
267 | XFS_STATS_INC(xs_ig_frecycle); | ||
268 | goto again; | ||
269 | } | ||
240 | 270 | ||
241 | vn_trace_exit(vp, "xfs_iget.alloc", | 271 | vn_trace_exit(vp, "xfs_iget.alloc", |
242 | (inst_t *)__return_address); | 272 | (inst_t *)__return_address); |
243 | 273 | ||
244 | XFS_STATS_INC(xs_ig_found); | 274 | XFS_STATS_INC(xs_ig_found); |
245 | 275 | ||
246 | spin_lock(&ip->i_flags_lock); | 276 | xfs_iflags_clear(ip, XFS_IRECLAIMABLE); |
247 | ip->i_flags &= ~XFS_IRECLAIMABLE; | ||
248 | spin_unlock(&ip->i_flags_lock); | ||
249 | version = ih->ih_version; | 277 | version = ih->ih_version; |
250 | read_unlock(&ih->ih_lock); | 278 | read_unlock(&ih->ih_lock); |
251 | xfs_ihash_promote(ih, ip, version); | 279 | xfs_ihash_promote(ih, ip, version); |
@@ -299,10 +327,7 @@ finish_inode: | |||
299 | if (lock_flags != 0) | 327 | if (lock_flags != 0) |
300 | xfs_ilock(ip, lock_flags); | 328 | xfs_ilock(ip, lock_flags); |
301 | 329 | ||
302 | spin_lock(&ip->i_flags_lock); | 330 | xfs_iflags_clear(ip, XFS_ISTALE); |
303 | ip->i_flags &= ~XFS_ISTALE; | ||
304 | spin_unlock(&ip->i_flags_lock); | ||
305 | |||
306 | vn_trace_exit(vp, "xfs_iget.found", | 331 | vn_trace_exit(vp, "xfs_iget.found", |
307 | (inst_t *)__return_address); | 332 | (inst_t *)__return_address); |
308 | goto return_ip; | 333 | goto return_ip; |
@@ -371,10 +396,7 @@ finish_inode: | |||
371 | ih->ih_next = ip; | 396 | ih->ih_next = ip; |
372 | ip->i_udquot = ip->i_gdquot = NULL; | 397 | ip->i_udquot = ip->i_gdquot = NULL; |
373 | ih->ih_version++; | 398 | ih->ih_version++; |
374 | spin_lock(&ip->i_flags_lock); | 399 | xfs_iflags_set(ip, XFS_INEW); |
375 | ip->i_flags |= XFS_INEW; | ||
376 | spin_unlock(&ip->i_flags_lock); | ||
377 | |||
378 | write_unlock(&ih->ih_lock); | 400 | write_unlock(&ih->ih_lock); |
379 | 401 | ||
380 | /* | 402 | /* |
@@ -625,7 +647,7 @@ xfs_iput_new(xfs_inode_t *ip, | |||
625 | vn_trace_entry(vp, "xfs_iput_new", (inst_t *)__return_address); | 647 | vn_trace_entry(vp, "xfs_iput_new", (inst_t *)__return_address); |
626 | 648 | ||
627 | if ((ip->i_d.di_mode == 0)) { | 649 | if ((ip->i_d.di_mode == 0)) { |
628 | ASSERT(!(ip->i_flags & XFS_IRECLAIMABLE)); | 650 | ASSERT(!xfs_iflags_test(ip, XFS_IRECLAIMABLE)); |
629 | vn_mark_bad(vp); | 651 | vn_mark_bad(vp); |
630 | } | 652 | } |
631 | if (inode->i_state & I_NEW) | 653 | if (inode->i_state & I_NEW) |
@@ -683,6 +705,7 @@ xfs_ireclaim(xfs_inode_t *ip) | |||
683 | /* | 705 | /* |
684 | * Free all memory associated with the inode. | 706 | * Free all memory associated with the inode. |
685 | */ | 707 | */ |
708 | xfs_iunlock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL); | ||
686 | xfs_idestroy(ip); | 709 | xfs_idestroy(ip); |
687 | } | 710 | } |
688 | 711 | ||
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index c27d7d495aa0..44dfac521285 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c | |||
@@ -2193,7 +2193,7 @@ xfs_ifree_cluster( | |||
2193 | /* Inode not in memory or we found it already, | 2193 | /* Inode not in memory or we found it already, |
2194 | * nothing to do | 2194 | * nothing to do |
2195 | */ | 2195 | */ |
2196 | if (!ip || (ip->i_flags & XFS_ISTALE)) { | 2196 | if (!ip || xfs_iflags_test(ip, XFS_ISTALE)) { |
2197 | read_unlock(&ih->ih_lock); | 2197 | read_unlock(&ih->ih_lock); |
2198 | continue; | 2198 | continue; |
2199 | } | 2199 | } |
@@ -2215,10 +2215,7 @@ xfs_ifree_cluster( | |||
2215 | 2215 | ||
2216 | if (ip == free_ip) { | 2216 | if (ip == free_ip) { |
2217 | if (xfs_iflock_nowait(ip)) { | 2217 | if (xfs_iflock_nowait(ip)) { |
2218 | spin_lock(&ip->i_flags_lock); | 2218 | xfs_iflags_set(ip, XFS_ISTALE); |
2219 | ip->i_flags |= XFS_ISTALE; | ||
2220 | spin_unlock(&ip->i_flags_lock); | ||
2221 | |||
2222 | if (xfs_inode_clean(ip)) { | 2219 | if (xfs_inode_clean(ip)) { |
2223 | xfs_ifunlock(ip); | 2220 | xfs_ifunlock(ip); |
2224 | } else { | 2221 | } else { |
@@ -2231,9 +2228,7 @@ xfs_ifree_cluster( | |||
2231 | 2228 | ||
2232 | if (xfs_ilock_nowait(ip, XFS_ILOCK_EXCL)) { | 2229 | if (xfs_ilock_nowait(ip, XFS_ILOCK_EXCL)) { |
2233 | if (xfs_iflock_nowait(ip)) { | 2230 | if (xfs_iflock_nowait(ip)) { |
2234 | spin_lock(&ip->i_flags_lock); | 2231 | xfs_iflags_set(ip, XFS_ISTALE); |
2235 | ip->i_flags |= XFS_ISTALE; | ||
2236 | spin_unlock(&ip->i_flags_lock); | ||
2237 | 2232 | ||
2238 | if (xfs_inode_clean(ip)) { | 2233 | if (xfs_inode_clean(ip)) { |
2239 | xfs_ifunlock(ip); | 2234 | xfs_ifunlock(ip); |
@@ -2263,9 +2258,7 @@ xfs_ifree_cluster( | |||
2263 | AIL_LOCK(mp,s); | 2258 | AIL_LOCK(mp,s); |
2264 | iip->ili_flush_lsn = iip->ili_item.li_lsn; | 2259 | iip->ili_flush_lsn = iip->ili_item.li_lsn; |
2265 | AIL_UNLOCK(mp, s); | 2260 | AIL_UNLOCK(mp, s); |
2266 | spin_lock(&iip->ili_inode->i_flags_lock); | 2261 | xfs_iflags_set(iip->ili_inode, XFS_ISTALE); |
2267 | iip->ili_inode->i_flags |= XFS_ISTALE; | ||
2268 | spin_unlock(&iip->ili_inode->i_flags_lock); | ||
2269 | pre_flushed++; | 2262 | pre_flushed++; |
2270 | } | 2263 | } |
2271 | lip = lip->li_bio_list; | 2264 | lip = lip->li_bio_list; |
@@ -2748,42 +2741,39 @@ xfs_iunpin( | |||
2748 | { | 2741 | { |
2749 | ASSERT(atomic_read(&ip->i_pincount) > 0); | 2742 | ASSERT(atomic_read(&ip->i_pincount) > 0); |
2750 | 2743 | ||
2751 | if (atomic_dec_and_test(&ip->i_pincount)) { | 2744 | if (atomic_dec_and_lock(&ip->i_pincount, &ip->i_flags_lock)) { |
2745 | |||
2752 | /* | 2746 | /* |
2753 | * If the inode is currently being reclaimed, the | 2747 | * If the inode is currently being reclaimed, the link between |
2754 | * linux inode _and_ the xfs vnode may have been | 2748 | * the bhv_vnode and the xfs_inode will be broken after the |
2755 | * freed so we cannot reference either of them safely. | 2749 | * XFS_IRECLAIM* flag is set. Hence, if these flags are not |
2756 | * Hence we should not try to do anything to them | 2750 | * set, then we can move forward and mark the linux inode dirty |
2757 | * if the xfs inode is currently in the reclaim | 2751 | * knowing that it is still valid as it won't freed until after |
2758 | * path. | 2752 | * the bhv_vnode<->xfs_inode link is broken in xfs_reclaim. The |
2753 | * i_flags_lock is used to synchronise the setting of the | ||
2754 | * XFS_IRECLAIM* flags and the breaking of the link, and so we | ||
2755 | * can execute atomically w.r.t to reclaim by holding this lock | ||
2756 | * here. | ||
2759 | * | 2757 | * |
2760 | * However, we still need to issue the unpin wakeup | 2758 | * However, we still need to issue the unpin wakeup call as the |
2761 | * call as the inode reclaim may be blocked waiting for | 2759 | * inode reclaim may be blocked waiting for the inode to become |
2762 | * the inode to become unpinned. | 2760 | * unpinned. |
2763 | */ | 2761 | */ |
2764 | struct inode *inode = NULL; | ||
2765 | 2762 | ||
2766 | spin_lock(&ip->i_flags_lock); | 2763 | if (!__xfs_iflags_test(ip, XFS_IRECLAIM|XFS_IRECLAIMABLE)) { |
2767 | if (!(ip->i_flags & (XFS_IRECLAIM|XFS_IRECLAIMABLE))) { | ||
2768 | bhv_vnode_t *vp = XFS_ITOV_NULL(ip); | 2764 | bhv_vnode_t *vp = XFS_ITOV_NULL(ip); |
2765 | struct inode *inode = NULL; | ||
2766 | |||
2767 | BUG_ON(vp == NULL); | ||
2768 | inode = vn_to_inode(vp); | ||
2769 | BUG_ON(inode->i_state & I_CLEAR); | ||
2769 | 2770 | ||
2770 | /* make sync come back and flush this inode */ | 2771 | /* make sync come back and flush this inode */ |
2771 | if (vp) { | 2772 | if (!(inode->i_state & (I_NEW|I_FREEING))) |
2772 | inode = vn_to_inode(vp); | 2773 | mark_inode_dirty_sync(inode); |
2773 | |||
2774 | if (!(inode->i_state & | ||
2775 | (I_NEW|I_FREEING|I_CLEAR))) { | ||
2776 | inode = igrab(inode); | ||
2777 | if (inode) | ||
2778 | mark_inode_dirty_sync(inode); | ||
2779 | } else | ||
2780 | inode = NULL; | ||
2781 | } | ||
2782 | } | 2774 | } |
2783 | spin_unlock(&ip->i_flags_lock); | 2775 | spin_unlock(&ip->i_flags_lock); |
2784 | wake_up(&ip->i_ipin_wait); | 2776 | wake_up(&ip->i_ipin_wait); |
2785 | if (inode) | ||
2786 | iput(inode); | ||
2787 | } | 2777 | } |
2788 | } | 2778 | } |
2789 | 2779 | ||
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index e96eb0835fe6..bc823720d88f 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h | |||
@@ -305,6 +305,47 @@ typedef struct xfs_inode { | |||
305 | #endif | 305 | #endif |
306 | } xfs_inode_t; | 306 | } xfs_inode_t; |
307 | 307 | ||
308 | |||
309 | /* | ||
310 | * i_flags helper functions | ||
311 | */ | ||
312 | static inline void | ||
313 | __xfs_iflags_set(xfs_inode_t *ip, unsigned short flags) | ||
314 | { | ||
315 | ip->i_flags |= flags; | ||
316 | } | ||
317 | |||
318 | static inline void | ||
319 | xfs_iflags_set(xfs_inode_t *ip, unsigned short flags) | ||
320 | { | ||
321 | spin_lock(&ip->i_flags_lock); | ||
322 | __xfs_iflags_set(ip, flags); | ||
323 | spin_unlock(&ip->i_flags_lock); | ||
324 | } | ||
325 | |||
326 | static inline void | ||
327 | xfs_iflags_clear(xfs_inode_t *ip, unsigned short flags) | ||
328 | { | ||
329 | spin_lock(&ip->i_flags_lock); | ||
330 | ip->i_flags &= ~flags; | ||
331 | spin_unlock(&ip->i_flags_lock); | ||
332 | } | ||
333 | |||
334 | static inline int | ||
335 | __xfs_iflags_test(xfs_inode_t *ip, unsigned short flags) | ||
336 | { | ||
337 | return (ip->i_flags & flags); | ||
338 | } | ||
339 | |||
340 | static inline int | ||
341 | xfs_iflags_test(xfs_inode_t *ip, unsigned short flags) | ||
342 | { | ||
343 | int ret; | ||
344 | spin_lock(&ip->i_flags_lock); | ||
345 | ret = __xfs_iflags_test(ip, flags); | ||
346 | spin_unlock(&ip->i_flags_lock); | ||
347 | return ret; | ||
348 | } | ||
308 | #endif /* __KERNEL__ */ | 349 | #endif /* __KERNEL__ */ |
309 | 350 | ||
310 | 351 | ||
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index 061e2ffdd1de..bda774a04b8f 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c | |||
@@ -1013,7 +1013,7 @@ xfs_readlink( | |||
1013 | pathlen = (int)ip->i_d.di_size; | 1013 | pathlen = (int)ip->i_d.di_size; |
1014 | 1014 | ||
1015 | if (ip->i_df.if_flags & XFS_IFINLINE) { | 1015 | if (ip->i_df.if_flags & XFS_IFINLINE) { |
1016 | error = uio_read(ip->i_df.if_u1.if_data, pathlen, uiop); | 1016 | error = xfs_uio_read(ip->i_df.if_u1.if_data, pathlen, uiop); |
1017 | } | 1017 | } |
1018 | else { | 1018 | else { |
1019 | /* | 1019 | /* |
@@ -1044,7 +1044,7 @@ xfs_readlink( | |||
1044 | byte_cnt = pathlen; | 1044 | byte_cnt = pathlen; |
1045 | pathlen -= byte_cnt; | 1045 | pathlen -= byte_cnt; |
1046 | 1046 | ||
1047 | error = uio_read(XFS_BUF_PTR(bp), byte_cnt, uiop); | 1047 | error = xfs_uio_read(XFS_BUF_PTR(bp), byte_cnt, uiop); |
1048 | xfs_buf_relse (bp); | 1048 | xfs_buf_relse (bp); |
1049 | } | 1049 | } |
1050 | 1050 | ||
@@ -3827,11 +3827,16 @@ xfs_reclaim( | |||
3827 | */ | 3827 | */ |
3828 | xfs_synchronize_atime(ip); | 3828 | xfs_synchronize_atime(ip); |
3829 | 3829 | ||
3830 | /* If we have nothing to flush with this inode then complete the | 3830 | /* |
3831 | * teardown now, otherwise break the link between the xfs inode | 3831 | * If we have nothing to flush with this inode then complete the |
3832 | * and the linux inode and clean up the xfs inode later. This | 3832 | * teardown now, otherwise break the link between the xfs inode and the |
3833 | * avoids flushing the inode to disk during the delete operation | 3833 | * linux inode and clean up the xfs inode later. This avoids flushing |
3834 | * itself. | 3834 | * the inode to disk during the delete operation itself. |
3835 | * | ||
3836 | * When breaking the link, we need to set the XFS_IRECLAIMABLE flag | ||
3837 | * first to ensure that xfs_iunpin() will never see an xfs inode | ||
3838 | * that has a linux inode being reclaimed. Synchronisation is provided | ||
3839 | * by the i_flags_lock. | ||
3835 | */ | 3840 | */ |
3836 | if (!ip->i_update_core && (ip->i_itemp == NULL)) { | 3841 | if (!ip->i_update_core && (ip->i_itemp == NULL)) { |
3837 | xfs_ilock(ip, XFS_ILOCK_EXCL); | 3842 | xfs_ilock(ip, XFS_ILOCK_EXCL); |
@@ -3840,13 +3845,13 @@ xfs_reclaim( | |||
3840 | } else { | 3845 | } else { |
3841 | xfs_mount_t *mp = ip->i_mount; | 3846 | xfs_mount_t *mp = ip->i_mount; |
3842 | 3847 | ||
3843 | /* Protect sync from us */ | 3848 | /* Protect sync and unpin from us */ |
3844 | XFS_MOUNT_ILOCK(mp); | 3849 | XFS_MOUNT_ILOCK(mp); |
3845 | vn_bhv_remove(VN_BHV_HEAD(vp), XFS_ITOBHV(ip)); | ||
3846 | list_add_tail(&ip->i_reclaim, &mp->m_del_inodes); | ||
3847 | spin_lock(&ip->i_flags_lock); | 3850 | spin_lock(&ip->i_flags_lock); |
3848 | ip->i_flags |= XFS_IRECLAIMABLE; | 3851 | __xfs_iflags_set(ip, XFS_IRECLAIMABLE); |
3852 | vn_bhv_remove(VN_BHV_HEAD(vp), XFS_ITOBHV(ip)); | ||
3849 | spin_unlock(&ip->i_flags_lock); | 3853 | spin_unlock(&ip->i_flags_lock); |
3854 | list_add_tail(&ip->i_reclaim, &mp->m_del_inodes); | ||
3850 | XFS_MOUNT_IUNLOCK(mp); | 3855 | XFS_MOUNT_IUNLOCK(mp); |
3851 | } | 3856 | } |
3852 | return 0; | 3857 | return 0; |
@@ -3872,8 +3877,8 @@ xfs_finish_reclaim( | |||
3872 | */ | 3877 | */ |
3873 | write_lock(&ih->ih_lock); | 3878 | write_lock(&ih->ih_lock); |
3874 | spin_lock(&ip->i_flags_lock); | 3879 | spin_lock(&ip->i_flags_lock); |
3875 | if ((ip->i_flags & XFS_IRECLAIM) || | 3880 | if (__xfs_iflags_test(ip, XFS_IRECLAIM) || |
3876 | (!(ip->i_flags & XFS_IRECLAIMABLE) && vp == NULL)) { | 3881 | (!__xfs_iflags_test(ip, XFS_IRECLAIMABLE) && vp == NULL)) { |
3877 | spin_unlock(&ip->i_flags_lock); | 3882 | spin_unlock(&ip->i_flags_lock); |
3878 | write_unlock(&ih->ih_lock); | 3883 | write_unlock(&ih->ih_lock); |
3879 | if (locked) { | 3884 | if (locked) { |
@@ -3882,7 +3887,7 @@ xfs_finish_reclaim( | |||
3882 | } | 3887 | } |
3883 | return 1; | 3888 | return 1; |
3884 | } | 3889 | } |
3885 | ip->i_flags |= XFS_IRECLAIM; | 3890 | __xfs_iflags_set(ip, XFS_IRECLAIM); |
3886 | spin_unlock(&ip->i_flags_lock); | 3891 | spin_unlock(&ip->i_flags_lock); |
3887 | write_unlock(&ih->ih_lock); | 3892 | write_unlock(&ih->ih_lock); |
3888 | 3893 | ||