diff options
Diffstat (limited to 'fs')
79 files changed, 911 insertions, 889 deletions
diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c index 1feb68ecef9..842d00048a6 100644 --- a/fs/autofs4/expire.c +++ b/fs/autofs4/expire.c | |||
@@ -94,25 +94,21 @@ static struct dentry *get_next_positive_subdir(struct dentry *prev, | |||
94 | { | 94 | { |
95 | struct autofs_sb_info *sbi = autofs4_sbi(root->d_sb); | 95 | struct autofs_sb_info *sbi = autofs4_sbi(root->d_sb); |
96 | struct list_head *next; | 96 | struct list_head *next; |
97 | struct dentry *p, *q; | 97 | struct dentry *q; |
98 | 98 | ||
99 | spin_lock(&sbi->lookup_lock); | 99 | spin_lock(&sbi->lookup_lock); |
100 | spin_lock(&root->d_lock); | ||
100 | 101 | ||
101 | if (prev == NULL) { | 102 | if (prev) |
102 | spin_lock(&root->d_lock); | 103 | next = prev->d_u.d_child.next; |
104 | else { | ||
103 | prev = dget_dlock(root); | 105 | prev = dget_dlock(root); |
104 | next = prev->d_subdirs.next; | 106 | next = prev->d_subdirs.next; |
105 | p = prev; | ||
106 | goto start; | ||
107 | } | 107 | } |
108 | 108 | ||
109 | p = prev; | 109 | cont: |
110 | spin_lock(&p->d_lock); | ||
111 | again: | ||
112 | next = p->d_u.d_child.next; | ||
113 | start: | ||
114 | if (next == &root->d_subdirs) { | 110 | if (next == &root->d_subdirs) { |
115 | spin_unlock(&p->d_lock); | 111 | spin_unlock(&root->d_lock); |
116 | spin_unlock(&sbi->lookup_lock); | 112 | spin_unlock(&sbi->lookup_lock); |
117 | dput(prev); | 113 | dput(prev); |
118 | return NULL; | 114 | return NULL; |
@@ -121,16 +117,15 @@ start: | |||
121 | q = list_entry(next, struct dentry, d_u.d_child); | 117 | q = list_entry(next, struct dentry, d_u.d_child); |
122 | 118 | ||
123 | spin_lock_nested(&q->d_lock, DENTRY_D_LOCK_NESTED); | 119 | spin_lock_nested(&q->d_lock, DENTRY_D_LOCK_NESTED); |
124 | /* Negative dentry - try next */ | 120 | /* Already gone or negative dentry (under construction) - try next */ |
125 | if (!simple_positive(q)) { | 121 | if (q->d_count == 0 || !simple_positive(q)) { |
126 | spin_unlock(&p->d_lock); | 122 | spin_unlock(&q->d_lock); |
127 | lock_set_subclass(&q->d_lock.dep_map, 0, _RET_IP_); | 123 | next = q->d_u.d_child.next; |
128 | p = q; | 124 | goto cont; |
129 | goto again; | ||
130 | } | 125 | } |
131 | dget_dlock(q); | 126 | dget_dlock(q); |
132 | spin_unlock(&q->d_lock); | 127 | spin_unlock(&q->d_lock); |
133 | spin_unlock(&p->d_lock); | 128 | spin_unlock(&root->d_lock); |
134 | spin_unlock(&sbi->lookup_lock); | 129 | spin_unlock(&sbi->lookup_lock); |
135 | 130 | ||
136 | dput(prev); | 131 | dput(prev); |
@@ -404,11 +399,6 @@ struct dentry *autofs4_expire_indirect(struct super_block *sb, | |||
404 | DPRINTK("checking mountpoint %p %.*s", | 399 | DPRINTK("checking mountpoint %p %.*s", |
405 | dentry, (int)dentry->d_name.len, dentry->d_name.name); | 400 | dentry, (int)dentry->d_name.len, dentry->d_name.name); |
406 | 401 | ||
407 | /* Path walk currently on this dentry? */ | ||
408 | ino_count = atomic_read(&ino->count) + 2; | ||
409 | if (dentry->d_count > ino_count) | ||
410 | goto next; | ||
411 | |||
412 | /* Can we umount this guy */ | 402 | /* Can we umount this guy */ |
413 | if (autofs4_mount_busy(mnt, dentry)) | 403 | if (autofs4_mount_busy(mnt, dentry)) |
414 | goto next; | 404 | goto next; |
@@ -1313,7 +1313,7 @@ EXPORT_SYMBOL(bio_copy_kern); | |||
1313 | * Note that this code is very hard to test under normal circumstances because | 1313 | * Note that this code is very hard to test under normal circumstances because |
1314 | * direct-io pins the pages with get_user_pages(). This makes | 1314 | * direct-io pins the pages with get_user_pages(). This makes |
1315 | * is_page_cache_freeable return false, and the VM will not clean the pages. | 1315 | * is_page_cache_freeable return false, and the VM will not clean the pages. |
1316 | * But other code (eg, pdflush) could clean the pages if they are mapped | 1316 | * But other code (eg, flusher threads) could clean the pages if they are mapped |
1317 | * pagecache. | 1317 | * pagecache. |
1318 | * | 1318 | * |
1319 | * Simply disabling the call to bio_set_pages_dirty() is a good way to test the | 1319 | * Simply disabling the call to bio_set_pages_dirty() is a good way to test the |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 83baec24946..6e8f416773d 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -324,7 +324,8 @@ static noinline int add_async_extent(struct async_cow *cow, | |||
324 | * If this code finds it can't get good compression, it puts an | 324 | * If this code finds it can't get good compression, it puts an |
325 | * entry onto the work queue to write the uncompressed bytes. This | 325 | * entry onto the work queue to write the uncompressed bytes. This |
326 | * makes sure that both compressed inodes and uncompressed inodes | 326 | * makes sure that both compressed inodes and uncompressed inodes |
327 | * are written in the same order that pdflush sent them down. | 327 | * are written in the same order that the flusher thread sent them |
328 | * down. | ||
328 | */ | 329 | */ |
329 | static noinline int compress_file_range(struct inode *inode, | 330 | static noinline int compress_file_range(struct inode *inode, |
330 | struct page *locked_page, | 331 | struct page *locked_page, |
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index bc2f6ffff3c..7bb755677a2 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
@@ -664,10 +664,6 @@ static noinline int btrfs_mksubvol(struct path *parent, | |||
664 | struct dentry *dentry; | 664 | struct dentry *dentry; |
665 | int error; | 665 | int error; |
666 | 666 | ||
667 | error = mnt_want_write(parent->mnt); | ||
668 | if (error) | ||
669 | return error; | ||
670 | |||
671 | mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT); | 667 | mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT); |
672 | 668 | ||
673 | dentry = lookup_one_len(name, parent->dentry, namelen); | 669 | dentry = lookup_one_len(name, parent->dentry, namelen); |
@@ -703,7 +699,6 @@ out_dput: | |||
703 | dput(dentry); | 699 | dput(dentry); |
704 | out_unlock: | 700 | out_unlock: |
705 | mutex_unlock(&dir->i_mutex); | 701 | mutex_unlock(&dir->i_mutex); |
706 | mnt_drop_write(parent->mnt); | ||
707 | return error; | 702 | return error; |
708 | } | 703 | } |
709 | 704 | ||
diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c index 643335a4fe3..051c7fe551d 100644 --- a/fs/btrfs/ordered-data.c +++ b/fs/btrfs/ordered-data.c | |||
@@ -596,7 +596,7 @@ void btrfs_start_ordered_extent(struct inode *inode, | |||
596 | /* | 596 | /* |
597 | * pages in the range can be dirty, clean or writeback. We | 597 | * pages in the range can be dirty, clean or writeback. We |
598 | * start IO on any dirty ones so the wait doesn't stall waiting | 598 | * start IO on any dirty ones so the wait doesn't stall waiting |
599 | * for pdflush to find them | 599 | * for the flusher thread to find them |
600 | */ | 600 | */ |
601 | if (!test_bit(BTRFS_ORDERED_DIRECT, &entry->flags)) | 601 | if (!test_bit(BTRFS_ORDERED_DIRECT, &entry->flags)) |
602 | filemap_fdatawrite_range(inode->i_mapping, start, end); | 602 | filemap_fdatawrite_range(inode->i_mapping, start, end); |
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 8c6e61d6eed..f2eb24c477a 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
@@ -100,10 +100,6 @@ static void __save_error_info(struct btrfs_fs_info *fs_info) | |||
100 | fs_info->fs_state = BTRFS_SUPER_FLAG_ERROR; | 100 | fs_info->fs_state = BTRFS_SUPER_FLAG_ERROR; |
101 | } | 101 | } |
102 | 102 | ||
103 | /* NOTE: | ||
104 | * We move write_super stuff at umount in order to avoid deadlock | ||
105 | * for umount hold all lock. | ||
106 | */ | ||
107 | static void save_error_info(struct btrfs_fs_info *fs_info) | 103 | static void save_error_info(struct btrfs_fs_info *fs_info) |
108 | { | 104 | { |
109 | __save_error_info(fs_info); | 105 | __save_error_info(fs_info); |
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index b8708f994e6..e86ae04abe6 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
@@ -1744,10 +1744,6 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path) | |||
1744 | 1744 | ||
1745 | device->fs_devices = root->fs_info->fs_devices; | 1745 | device->fs_devices = root->fs_info->fs_devices; |
1746 | 1746 | ||
1747 | /* | ||
1748 | * we don't want write_supers to jump in here with our device | ||
1749 | * half setup | ||
1750 | */ | ||
1751 | mutex_lock(&root->fs_info->fs_devices->device_list_mutex); | 1747 | mutex_lock(&root->fs_info->fs_devices->device_list_mutex); |
1752 | list_add_rcu(&device->dev_list, &root->fs_info->fs_devices->devices); | 1748 | list_add_rcu(&device->dev_list, &root->fs_info->fs_devices->devices); |
1753 | list_add(&device->dev_alloc_list, | 1749 | list_add(&device->dev_alloc_list, |
diff --git a/fs/ceph/debugfs.c b/fs/ceph/debugfs.c index fb962efdace..6d59006bfa2 100644 --- a/fs/ceph/debugfs.c +++ b/fs/ceph/debugfs.c | |||
@@ -201,6 +201,7 @@ int ceph_fs_debugfs_init(struct ceph_fs_client *fsc) | |||
201 | int err = -ENOMEM; | 201 | int err = -ENOMEM; |
202 | 202 | ||
203 | dout("ceph_fs_debugfs_init\n"); | 203 | dout("ceph_fs_debugfs_init\n"); |
204 | BUG_ON(!fsc->client->debugfs_dir); | ||
204 | fsc->debugfs_congestion_kb = | 205 | fsc->debugfs_congestion_kb = |
205 | debugfs_create_file("writeback_congestion_kb", | 206 | debugfs_create_file("writeback_congestion_kb", |
206 | 0600, | 207 | 0600, |
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c index f391f1e7541..e5b77319c97 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c | |||
@@ -633,44 +633,6 @@ static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry, | |||
633 | return dentry; | 633 | return dentry; |
634 | } | 634 | } |
635 | 635 | ||
636 | int ceph_atomic_open(struct inode *dir, struct dentry *dentry, | ||
637 | struct file *file, unsigned flags, umode_t mode, | ||
638 | int *opened) | ||
639 | { | ||
640 | int err; | ||
641 | struct dentry *res = NULL; | ||
642 | |||
643 | if (!(flags & O_CREAT)) { | ||
644 | if (dentry->d_name.len > NAME_MAX) | ||
645 | return -ENAMETOOLONG; | ||
646 | |||
647 | err = ceph_init_dentry(dentry); | ||
648 | if (err < 0) | ||
649 | return err; | ||
650 | |||
651 | return ceph_lookup_open(dir, dentry, file, flags, mode, opened); | ||
652 | } | ||
653 | |||
654 | if (d_unhashed(dentry)) { | ||
655 | res = ceph_lookup(dir, dentry, 0); | ||
656 | if (IS_ERR(res)) | ||
657 | return PTR_ERR(res); | ||
658 | |||
659 | if (res) | ||
660 | dentry = res; | ||
661 | } | ||
662 | |||
663 | /* We don't deal with positive dentries here */ | ||
664 | if (dentry->d_inode) | ||
665 | return finish_no_open(file, res); | ||
666 | |||
667 | *opened |= FILE_CREATED; | ||
668 | err = ceph_lookup_open(dir, dentry, file, flags, mode, opened); | ||
669 | dput(res); | ||
670 | |||
671 | return err; | ||
672 | } | ||
673 | |||
674 | /* | 636 | /* |
675 | * If we do a create but get no trace back from the MDS, follow up with | 637 | * If we do a create but get no trace back from the MDS, follow up with |
676 | * a lookup (the VFS expects us to link up the provided dentry). | 638 | * a lookup (the VFS expects us to link up the provided dentry). |
diff --git a/fs/ceph/file.c b/fs/ceph/file.c index 1b81d6c3187..ecebbc09bfc 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c | |||
@@ -4,6 +4,7 @@ | |||
4 | #include <linux/sched.h> | 4 | #include <linux/sched.h> |
5 | #include <linux/slab.h> | 5 | #include <linux/slab.h> |
6 | #include <linux/file.h> | 6 | #include <linux/file.h> |
7 | #include <linux/mount.h> | ||
7 | #include <linux/namei.h> | 8 | #include <linux/namei.h> |
8 | #include <linux/writeback.h> | 9 | #include <linux/writeback.h> |
9 | 10 | ||
@@ -106,9 +107,6 @@ static int ceph_init_file(struct inode *inode, struct file *file, int fmode) | |||
106 | } | 107 | } |
107 | 108 | ||
108 | /* | 109 | /* |
109 | * If the filp already has private_data, that means the file was | ||
110 | * already opened by intent during lookup, and we do nothing. | ||
111 | * | ||
112 | * If we already have the requisite capabilities, we can satisfy | 110 | * If we already have the requisite capabilities, we can satisfy |
113 | * the open request locally (no need to request new caps from the | 111 | * the open request locally (no need to request new caps from the |
114 | * MDS). We do, however, need to inform the MDS (asynchronously) | 112 | * MDS). We do, however, need to inform the MDS (asynchronously) |
@@ -207,24 +205,29 @@ out: | |||
207 | 205 | ||
208 | 206 | ||
209 | /* | 207 | /* |
210 | * Do a lookup + open with a single request. | 208 | * Do a lookup + open with a single request. If we get a non-existent |
211 | * | 209 | * file or symlink, return 1 so the VFS can retry. |
212 | * If this succeeds, but some subsequent check in the vfs | ||
213 | * may_open() fails, the struct *file gets cleaned up (i.e. | ||
214 | * ceph_release gets called). So fear not! | ||
215 | */ | 210 | */ |
216 | int ceph_lookup_open(struct inode *dir, struct dentry *dentry, | 211 | int ceph_atomic_open(struct inode *dir, struct dentry *dentry, |
217 | struct file *file, unsigned flags, umode_t mode, | 212 | struct file *file, unsigned flags, umode_t mode, |
218 | int *opened) | 213 | int *opened) |
219 | { | 214 | { |
220 | struct ceph_fs_client *fsc = ceph_sb_to_client(dir->i_sb); | 215 | struct ceph_fs_client *fsc = ceph_sb_to_client(dir->i_sb); |
221 | struct ceph_mds_client *mdsc = fsc->mdsc; | 216 | struct ceph_mds_client *mdsc = fsc->mdsc; |
222 | struct ceph_mds_request *req; | 217 | struct ceph_mds_request *req; |
223 | struct dentry *ret; | 218 | struct dentry *dn; |
224 | int err; | 219 | int err; |
225 | 220 | ||
226 | dout("ceph_lookup_open dentry %p '%.*s' flags %d mode 0%o\n", | 221 | dout("atomic_open %p dentry %p '%.*s' %s flags %d mode 0%o\n", |
227 | dentry, dentry->d_name.len, dentry->d_name.name, flags, mode); | 222 | dir, dentry, dentry->d_name.len, dentry->d_name.name, |
223 | d_unhashed(dentry) ? "unhashed" : "hashed", flags, mode); | ||
224 | |||
225 | if (dentry->d_name.len > NAME_MAX) | ||
226 | return -ENAMETOOLONG; | ||
227 | |||
228 | err = ceph_init_dentry(dentry); | ||
229 | if (err < 0) | ||
230 | return err; | ||
228 | 231 | ||
229 | /* do the open */ | 232 | /* do the open */ |
230 | req = prepare_open_request(dir->i_sb, flags, mode); | 233 | req = prepare_open_request(dir->i_sb, flags, mode); |
@@ -241,22 +244,31 @@ int ceph_lookup_open(struct inode *dir, struct dentry *dentry, | |||
241 | (flags & (O_CREAT|O_TRUNC)) ? dir : NULL, | 244 | (flags & (O_CREAT|O_TRUNC)) ? dir : NULL, |
242 | req); | 245 | req); |
243 | err = ceph_handle_snapdir(req, dentry, err); | 246 | err = ceph_handle_snapdir(req, dentry, err); |
244 | if (err) | 247 | if (err == 0 && (flags & O_CREAT) && !req->r_reply_info.head->is_dentry) |
245 | goto out; | ||
246 | if ((flags & O_CREAT) && !req->r_reply_info.head->is_dentry) | ||
247 | err = ceph_handle_notrace_create(dir, dentry); | 248 | err = ceph_handle_notrace_create(dir, dentry); |
248 | if (err) | ||
249 | goto out; | ||
250 | err = finish_open(file, req->r_dentry, ceph_open, opened); | ||
251 | out: | ||
252 | ret = ceph_finish_lookup(req, dentry, err); | ||
253 | ceph_mdsc_put_request(req); | ||
254 | dout("ceph_lookup_open result=%p\n", ret); | ||
255 | 249 | ||
256 | if (IS_ERR(ret)) | 250 | if (d_unhashed(dentry)) { |
257 | return PTR_ERR(ret); | 251 | dn = ceph_finish_lookup(req, dentry, err); |
252 | if (IS_ERR(dn)) | ||
253 | err = PTR_ERR(dn); | ||
254 | } else { | ||
255 | /* we were given a hashed negative dentry */ | ||
256 | dn = NULL; | ||
257 | } | ||
258 | if (err) | ||
259 | goto out_err; | ||
260 | if (dn || dentry->d_inode == NULL || S_ISLNK(dentry->d_inode->i_mode)) { | ||
261 | /* make vfs retry on splice, ENOENT, or symlink */ | ||
262 | dout("atomic_open finish_no_open on dn %p\n", dn); | ||
263 | err = finish_no_open(file, dn); | ||
264 | } else { | ||
265 | dout("atomic_open finish_open on dn %p\n", dn); | ||
266 | err = finish_open(file, dentry, ceph_open, opened); | ||
267 | } | ||
258 | 268 | ||
259 | dput(ret); | 269 | out_err: |
270 | ceph_mdsc_put_request(req); | ||
271 | dout("atomic_open result=%d\n", err); | ||
260 | return err; | 272 | return err; |
261 | } | 273 | } |
262 | 274 | ||
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index 9fff9f3b17e..4b5762ef7c2 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c | |||
@@ -992,11 +992,15 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req, | |||
992 | if (rinfo->head->is_dentry) { | 992 | if (rinfo->head->is_dentry) { |
993 | struct inode *dir = req->r_locked_dir; | 993 | struct inode *dir = req->r_locked_dir; |
994 | 994 | ||
995 | err = fill_inode(dir, &rinfo->diri, rinfo->dirfrag, | 995 | if (dir) { |
996 | session, req->r_request_started, -1, | 996 | err = fill_inode(dir, &rinfo->diri, rinfo->dirfrag, |
997 | &req->r_caps_reservation); | 997 | session, req->r_request_started, -1, |
998 | if (err < 0) | 998 | &req->r_caps_reservation); |
999 | return err; | 999 | if (err < 0) |
1000 | return err; | ||
1001 | } else { | ||
1002 | WARN_ON_ONCE(1); | ||
1003 | } | ||
1000 | } | 1004 | } |
1001 | 1005 | ||
1002 | /* | 1006 | /* |
@@ -1004,6 +1008,7 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req, | |||
1004 | * will have trouble splicing in the virtual snapdir later | 1008 | * will have trouble splicing in the virtual snapdir later |
1005 | */ | 1009 | */ |
1006 | if (rinfo->head->is_dentry && !req->r_aborted && | 1010 | if (rinfo->head->is_dentry && !req->r_aborted && |
1011 | req->r_locked_dir && | ||
1007 | (rinfo->head->is_target || strncmp(req->r_dentry->d_name.name, | 1012 | (rinfo->head->is_target || strncmp(req->r_dentry->d_name.name, |
1008 | fsc->mount_options->snapdir_name, | 1013 | fsc->mount_options->snapdir_name, |
1009 | req->r_dentry->d_name.len))) { | 1014 | req->r_dentry->d_name.len))) { |
diff --git a/fs/ceph/ioctl.c b/fs/ceph/ioctl.c index 8e3fb69fbe6..1396ceb4679 100644 --- a/fs/ceph/ioctl.c +++ b/fs/ceph/ioctl.c | |||
@@ -42,7 +42,8 @@ static long __validate_layout(struct ceph_mds_client *mdsc, | |||
42 | /* validate striping parameters */ | 42 | /* validate striping parameters */ |
43 | if ((l->object_size & ~PAGE_MASK) || | 43 | if ((l->object_size & ~PAGE_MASK) || |
44 | (l->stripe_unit & ~PAGE_MASK) || | 44 | (l->stripe_unit & ~PAGE_MASK) || |
45 | ((unsigned)l->object_size % (unsigned)l->stripe_unit)) | 45 | (l->stripe_unit != 0 && |
46 | ((unsigned)l->object_size % (unsigned)l->stripe_unit))) | ||
46 | return -EINVAL; | 47 | return -EINVAL; |
47 | 48 | ||
48 | /* make sure it's a valid data pool */ | 49 | /* make sure it's a valid data pool */ |
diff --git a/fs/ceph/super.h b/fs/ceph/super.h index ebc95cc652b..66ebe720e40 100644 --- a/fs/ceph/super.h +++ b/fs/ceph/super.h | |||
@@ -806,9 +806,9 @@ extern int ceph_copy_from_page_vector(struct page **pages, | |||
806 | loff_t off, size_t len); | 806 | loff_t off, size_t len); |
807 | extern struct page **ceph_alloc_page_vector(int num_pages, gfp_t flags); | 807 | extern struct page **ceph_alloc_page_vector(int num_pages, gfp_t flags); |
808 | extern int ceph_open(struct inode *inode, struct file *file); | 808 | extern int ceph_open(struct inode *inode, struct file *file); |
809 | extern int ceph_lookup_open(struct inode *dir, struct dentry *dentry, | 809 | extern int ceph_atomic_open(struct inode *dir, struct dentry *dentry, |
810 | struct file *od, unsigned flags, | 810 | struct file *file, unsigned flags, umode_t mode, |
811 | umode_t mode, int *opened); | 811 | int *opened); |
812 | extern int ceph_release(struct inode *inode, struct file *filp); | 812 | extern int ceph_release(struct inode *inode, struct file *filp); |
813 | 813 | ||
814 | /* dir.c */ | 814 | /* dir.c */ |
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 497da5ce704..977dc0e85cc 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
@@ -246,6 +246,16 @@ struct smb_version_operations { | |||
246 | bool (*can_echo)(struct TCP_Server_Info *); | 246 | bool (*can_echo)(struct TCP_Server_Info *); |
247 | /* send echo request */ | 247 | /* send echo request */ |
248 | int (*echo)(struct TCP_Server_Info *); | 248 | int (*echo)(struct TCP_Server_Info *); |
249 | /* create directory */ | ||
250 | int (*mkdir)(const unsigned int, struct cifs_tcon *, const char *, | ||
251 | struct cifs_sb_info *); | ||
252 | /* set info on created directory */ | ||
253 | void (*mkdir_setinfo)(struct inode *, const char *, | ||
254 | struct cifs_sb_info *, struct cifs_tcon *, | ||
255 | const unsigned int); | ||
256 | /* remove directory */ | ||
257 | int (*rmdir)(const unsigned int, struct cifs_tcon *, const char *, | ||
258 | struct cifs_sb_info *); | ||
249 | }; | 259 | }; |
250 | 260 | ||
251 | struct smb_version_values { | 261 | struct smb_version_values { |
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index cf7fb185103..f1bbf8305d3 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
@@ -289,18 +289,15 @@ extern int CIFSSMBUnixSetFileInfo(const unsigned int xid, | |||
289 | u16 fid, u32 pid_of_opener); | 289 | u16 fid, u32 pid_of_opener); |
290 | 290 | ||
291 | extern int CIFSSMBUnixSetPathInfo(const unsigned int xid, | 291 | extern int CIFSSMBUnixSetPathInfo(const unsigned int xid, |
292 | struct cifs_tcon *tcon, char *file_name, | 292 | struct cifs_tcon *tcon, const char *file_name, |
293 | const struct cifs_unix_set_info_args *args, | 293 | const struct cifs_unix_set_info_args *args, |
294 | const struct nls_table *nls_codepage, | 294 | const struct nls_table *nls_codepage, |
295 | int remap_special_chars); | 295 | int remap); |
296 | 296 | ||
297 | extern int CIFSSMBMkDir(const unsigned int xid, struct cifs_tcon *tcon, | 297 | extern int CIFSSMBMkDir(const unsigned int xid, struct cifs_tcon *tcon, |
298 | const char *newName, | 298 | const char *name, struct cifs_sb_info *cifs_sb); |
299 | const struct nls_table *nls_codepage, | ||
300 | int remap_special_chars); | ||
301 | extern int CIFSSMBRmDir(const unsigned int xid, struct cifs_tcon *tcon, | 299 | extern int CIFSSMBRmDir(const unsigned int xid, struct cifs_tcon *tcon, |
302 | const char *name, const struct nls_table *nls_codepage, | 300 | const char *name, struct cifs_sb_info *cifs_sb); |
303 | int remap_special_chars); | ||
304 | extern int CIFSPOSIXDelFile(const unsigned int xid, struct cifs_tcon *tcon, | 301 | extern int CIFSPOSIXDelFile(const unsigned int xid, struct cifs_tcon *tcon, |
305 | const char *name, __u16 type, | 302 | const char *name, __u16 type, |
306 | const struct nls_table *nls_codepage, | 303 | const struct nls_table *nls_codepage, |
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index cabc7a01f5d..074923ce593 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
@@ -948,15 +948,15 @@ DelFileRetry: | |||
948 | } | 948 | } |
949 | 949 | ||
950 | int | 950 | int |
951 | CIFSSMBRmDir(const unsigned int xid, struct cifs_tcon *tcon, | 951 | CIFSSMBRmDir(const unsigned int xid, struct cifs_tcon *tcon, const char *name, |
952 | const char *dirName, const struct nls_table *nls_codepage, | 952 | struct cifs_sb_info *cifs_sb) |
953 | int remap) | ||
954 | { | 953 | { |
955 | DELETE_DIRECTORY_REQ *pSMB = NULL; | 954 | DELETE_DIRECTORY_REQ *pSMB = NULL; |
956 | DELETE_DIRECTORY_RSP *pSMBr = NULL; | 955 | DELETE_DIRECTORY_RSP *pSMBr = NULL; |
957 | int rc = 0; | 956 | int rc = 0; |
958 | int bytes_returned; | 957 | int bytes_returned; |
959 | int name_len; | 958 | int name_len; |
959 | int remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR; | ||
960 | 960 | ||
961 | cFYI(1, "In CIFSSMBRmDir"); | 961 | cFYI(1, "In CIFSSMBRmDir"); |
962 | RmDirRetry: | 962 | RmDirRetry: |
@@ -966,14 +966,15 @@ RmDirRetry: | |||
966 | return rc; | 966 | return rc; |
967 | 967 | ||
968 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { | 968 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { |
969 | name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, dirName, | 969 | name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, name, |
970 | PATH_MAX, nls_codepage, remap); | 970 | PATH_MAX, cifs_sb->local_nls, |
971 | remap); | ||
971 | name_len++; /* trailing null */ | 972 | name_len++; /* trailing null */ |
972 | name_len *= 2; | 973 | name_len *= 2; |
973 | } else { /* BB improve check for buffer overruns BB */ | 974 | } else { /* BB improve check for buffer overruns BB */ |
974 | name_len = strnlen(dirName, PATH_MAX); | 975 | name_len = strnlen(name, PATH_MAX); |
975 | name_len++; /* trailing null */ | 976 | name_len++; /* trailing null */ |
976 | strncpy(pSMB->DirName, dirName, name_len); | 977 | strncpy(pSMB->DirName, name, name_len); |
977 | } | 978 | } |
978 | 979 | ||
979 | pSMB->BufferFormat = 0x04; | 980 | pSMB->BufferFormat = 0x04; |
@@ -992,14 +993,15 @@ RmDirRetry: | |||
992 | } | 993 | } |
993 | 994 | ||
994 | int | 995 | int |
995 | CIFSSMBMkDir(const unsigned int xid, struct cifs_tcon *tcon, | 996 | CIFSSMBMkDir(const unsigned int xid, struct cifs_tcon *tcon, const char *name, |
996 | const char *name, const struct nls_table *nls_codepage, int remap) | 997 | struct cifs_sb_info *cifs_sb) |
997 | { | 998 | { |
998 | int rc = 0; | 999 | int rc = 0; |
999 | CREATE_DIRECTORY_REQ *pSMB = NULL; | 1000 | CREATE_DIRECTORY_REQ *pSMB = NULL; |
1000 | CREATE_DIRECTORY_RSP *pSMBr = NULL; | 1001 | CREATE_DIRECTORY_RSP *pSMBr = NULL; |
1001 | int bytes_returned; | 1002 | int bytes_returned; |
1002 | int name_len; | 1003 | int name_len; |
1004 | int remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR; | ||
1003 | 1005 | ||
1004 | cFYI(1, "In CIFSSMBMkDir"); | 1006 | cFYI(1, "In CIFSSMBMkDir"); |
1005 | MkDirRetry: | 1007 | MkDirRetry: |
@@ -1010,7 +1012,8 @@ MkDirRetry: | |||
1010 | 1012 | ||
1011 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { | 1013 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { |
1012 | name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, name, | 1014 | name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, name, |
1013 | PATH_MAX, nls_codepage, remap); | 1015 | PATH_MAX, cifs_sb->local_nls, |
1016 | remap); | ||
1014 | name_len++; /* trailing null */ | 1017 | name_len++; /* trailing null */ |
1015 | name_len *= 2; | 1018 | name_len *= 2; |
1016 | } else { /* BB improve check for buffer overruns BB */ | 1019 | } else { /* BB improve check for buffer overruns BB */ |
@@ -5943,7 +5946,7 @@ CIFSSMBUnixSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon, | |||
5943 | 5946 | ||
5944 | int | 5947 | int |
5945 | CIFSSMBUnixSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon, | 5948 | CIFSSMBUnixSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon, |
5946 | char *fileName, | 5949 | const char *file_name, |
5947 | const struct cifs_unix_set_info_args *args, | 5950 | const struct cifs_unix_set_info_args *args, |
5948 | const struct nls_table *nls_codepage, int remap) | 5951 | const struct nls_table *nls_codepage, int remap) |
5949 | { | 5952 | { |
@@ -5964,14 +5967,14 @@ setPermsRetry: | |||
5964 | 5967 | ||
5965 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { | 5968 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { |
5966 | name_len = | 5969 | name_len = |
5967 | cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName, | 5970 | cifsConvertToUTF16((__le16 *) pSMB->FileName, file_name, |
5968 | PATH_MAX, nls_codepage, remap); | 5971 | PATH_MAX, nls_codepage, remap); |
5969 | name_len++; /* trailing null */ | 5972 | name_len++; /* trailing null */ |
5970 | name_len *= 2; | 5973 | name_len *= 2; |
5971 | } else { /* BB improve the check for buffer overruns BB */ | 5974 | } else { /* BB improve the check for buffer overruns BB */ |
5972 | name_len = strnlen(fileName, PATH_MAX); | 5975 | name_len = strnlen(file_name, PATH_MAX); |
5973 | name_len++; /* trailing null */ | 5976 | name_len++; /* trailing null */ |
5974 | strncpy(pSMB->FileName, fileName, name_len); | 5977 | strncpy(pSMB->FileName, file_name, name_len); |
5975 | } | 5978 | } |
5976 | 5979 | ||
5977 | params = 6 + name_len; | 5980 | params = 6 + name_len; |
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 35cb6a374a4..7354877fa3b 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -1219,16 +1219,153 @@ unlink_out: | |||
1219 | return rc; | 1219 | return rc; |
1220 | } | 1220 | } |
1221 | 1221 | ||
1222 | static int | ||
1223 | cifs_mkdir_qinfo(struct inode *inode, struct dentry *dentry, umode_t mode, | ||
1224 | const char *full_path, struct cifs_sb_info *cifs_sb, | ||
1225 | struct cifs_tcon *tcon, const unsigned int xid) | ||
1226 | { | ||
1227 | int rc = 0; | ||
1228 | struct inode *newinode = NULL; | ||
1229 | |||
1230 | if (tcon->unix_ext) | ||
1231 | rc = cifs_get_inode_info_unix(&newinode, full_path, inode->i_sb, | ||
1232 | xid); | ||
1233 | else | ||
1234 | rc = cifs_get_inode_info(&newinode, full_path, NULL, | ||
1235 | inode->i_sb, xid, NULL); | ||
1236 | if (rc) | ||
1237 | return rc; | ||
1238 | |||
1239 | d_instantiate(dentry, newinode); | ||
1240 | /* | ||
1241 | * setting nlink not necessary except in cases where we failed to get it | ||
1242 | * from the server or was set bogus | ||
1243 | */ | ||
1244 | if ((dentry->d_inode) && (dentry->d_inode->i_nlink < 2)) | ||
1245 | set_nlink(dentry->d_inode, 2); | ||
1246 | |||
1247 | mode &= ~current_umask(); | ||
1248 | /* must turn on setgid bit if parent dir has it */ | ||
1249 | if (inode->i_mode & S_ISGID) | ||
1250 | mode |= S_ISGID; | ||
1251 | |||
1252 | if (tcon->unix_ext) { | ||
1253 | struct cifs_unix_set_info_args args = { | ||
1254 | .mode = mode, | ||
1255 | .ctime = NO_CHANGE_64, | ||
1256 | .atime = NO_CHANGE_64, | ||
1257 | .mtime = NO_CHANGE_64, | ||
1258 | .device = 0, | ||
1259 | }; | ||
1260 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { | ||
1261 | args.uid = (__u64)current_fsuid(); | ||
1262 | if (inode->i_mode & S_ISGID) | ||
1263 | args.gid = (__u64)inode->i_gid; | ||
1264 | else | ||
1265 | args.gid = (__u64)current_fsgid(); | ||
1266 | } else { | ||
1267 | args.uid = NO_CHANGE_64; | ||
1268 | args.gid = NO_CHANGE_64; | ||
1269 | } | ||
1270 | CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args, | ||
1271 | cifs_sb->local_nls, | ||
1272 | cifs_sb->mnt_cifs_flags & | ||
1273 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
1274 | } else { | ||
1275 | struct TCP_Server_Info *server = tcon->ses->server; | ||
1276 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) && | ||
1277 | (mode & S_IWUGO) == 0 && server->ops->mkdir_setinfo) | ||
1278 | server->ops->mkdir_setinfo(newinode, full_path, cifs_sb, | ||
1279 | tcon, xid); | ||
1280 | if (dentry->d_inode) { | ||
1281 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) | ||
1282 | dentry->d_inode->i_mode = (mode | S_IFDIR); | ||
1283 | |||
1284 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { | ||
1285 | dentry->d_inode->i_uid = current_fsuid(); | ||
1286 | if (inode->i_mode & S_ISGID) | ||
1287 | dentry->d_inode->i_gid = inode->i_gid; | ||
1288 | else | ||
1289 | dentry->d_inode->i_gid = | ||
1290 | current_fsgid(); | ||
1291 | } | ||
1292 | } | ||
1293 | } | ||
1294 | return rc; | ||
1295 | } | ||
1296 | |||
1297 | static int | ||
1298 | cifs_posix_mkdir(struct inode *inode, struct dentry *dentry, umode_t mode, | ||
1299 | const char *full_path, struct cifs_sb_info *cifs_sb, | ||
1300 | struct cifs_tcon *tcon, const unsigned int xid) | ||
1301 | { | ||
1302 | int rc = 0; | ||
1303 | u32 oplock = 0; | ||
1304 | FILE_UNIX_BASIC_INFO *info = NULL; | ||
1305 | struct inode *newinode = NULL; | ||
1306 | struct cifs_fattr fattr; | ||
1307 | |||
1308 | info = kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL); | ||
1309 | if (info == NULL) { | ||
1310 | rc = -ENOMEM; | ||
1311 | goto posix_mkdir_out; | ||
1312 | } | ||
1313 | |||
1314 | mode &= ~current_umask(); | ||
1315 | rc = CIFSPOSIXCreate(xid, tcon, SMB_O_DIRECTORY | SMB_O_CREAT, mode, | ||
1316 | NULL /* netfid */, info, &oplock, full_path, | ||
1317 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & | ||
1318 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
1319 | if (rc == -EOPNOTSUPP) | ||
1320 | goto posix_mkdir_out; | ||
1321 | else if (rc) { | ||
1322 | cFYI(1, "posix mkdir returned 0x%x", rc); | ||
1323 | d_drop(dentry); | ||
1324 | goto posix_mkdir_out; | ||
1325 | } | ||
1326 | |||
1327 | if (info->Type == cpu_to_le32(-1)) | ||
1328 | /* no return info, go query for it */ | ||
1329 | goto posix_mkdir_get_info; | ||
1330 | /* | ||
1331 | * BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if | ||
1332 | * need to set uid/gid. | ||
1333 | */ | ||
1334 | |||
1335 | cifs_unix_basic_to_fattr(&fattr, info, cifs_sb); | ||
1336 | cifs_fill_uniqueid(inode->i_sb, &fattr); | ||
1337 | newinode = cifs_iget(inode->i_sb, &fattr); | ||
1338 | if (!newinode) | ||
1339 | goto posix_mkdir_get_info; | ||
1340 | |||
1341 | d_instantiate(dentry, newinode); | ||
1342 | |||
1343 | #ifdef CONFIG_CIFS_DEBUG2 | ||
1344 | cFYI(1, "instantiated dentry %p %s to inode %p", dentry, | ||
1345 | dentry->d_name.name, newinode); | ||
1346 | |||
1347 | if (newinode->i_nlink != 2) | ||
1348 | cFYI(1, "unexpected number of links %d", newinode->i_nlink); | ||
1349 | #endif | ||
1350 | |||
1351 | posix_mkdir_out: | ||
1352 | kfree(info); | ||
1353 | return rc; | ||
1354 | posix_mkdir_get_info: | ||
1355 | rc = cifs_mkdir_qinfo(inode, dentry, mode, full_path, cifs_sb, tcon, | ||
1356 | xid); | ||
1357 | goto posix_mkdir_out; | ||
1358 | } | ||
1359 | |||
1222 | int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode) | 1360 | int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode) |
1223 | { | 1361 | { |
1224 | int rc = 0, tmprc; | 1362 | int rc = 0; |
1225 | unsigned int xid; | 1363 | unsigned int xid; |
1226 | struct cifs_sb_info *cifs_sb; | 1364 | struct cifs_sb_info *cifs_sb; |
1227 | struct tcon_link *tlink; | 1365 | struct tcon_link *tlink; |
1228 | struct cifs_tcon *tcon; | 1366 | struct cifs_tcon *tcon; |
1229 | char *full_path = NULL; | 1367 | struct TCP_Server_Info *server; |
1230 | struct inode *newinode = NULL; | 1368 | char *full_path; |
1231 | struct cifs_fattr fattr; | ||
1232 | 1369 | ||
1233 | cFYI(1, "In cifs_mkdir, mode = 0x%hx inode = 0x%p", mode, inode); | 1370 | cFYI(1, "In cifs_mkdir, mode = 0x%hx inode = 0x%p", mode, inode); |
1234 | 1371 | ||
@@ -1248,145 +1385,29 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode) | |||
1248 | 1385 | ||
1249 | if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP & | 1386 | if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP & |
1250 | le64_to_cpu(tcon->fsUnixInfo.Capability))) { | 1387 | le64_to_cpu(tcon->fsUnixInfo.Capability))) { |
1251 | u32 oplock = 0; | 1388 | rc = cifs_posix_mkdir(inode, direntry, mode, full_path, cifs_sb, |
1252 | FILE_UNIX_BASIC_INFO *pInfo = | 1389 | tcon, xid); |
1253 | kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL); | 1390 | if (rc != -EOPNOTSUPP) |
1254 | if (pInfo == NULL) { | ||
1255 | rc = -ENOMEM; | ||
1256 | goto mkdir_out; | 1391 | goto mkdir_out; |
1257 | } | 1392 | } |
1258 | |||
1259 | mode &= ~current_umask(); | ||
1260 | rc = CIFSPOSIXCreate(xid, tcon, SMB_O_DIRECTORY | SMB_O_CREAT, | ||
1261 | mode, NULL /* netfid */, pInfo, &oplock, | ||
1262 | full_path, cifs_sb->local_nls, | ||
1263 | cifs_sb->mnt_cifs_flags & | ||
1264 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
1265 | if (rc == -EOPNOTSUPP) { | ||
1266 | kfree(pInfo); | ||
1267 | goto mkdir_retry_old; | ||
1268 | } else if (rc) { | ||
1269 | cFYI(1, "posix mkdir returned 0x%x", rc); | ||
1270 | d_drop(direntry); | ||
1271 | } else { | ||
1272 | if (pInfo->Type == cpu_to_le32(-1)) { | ||
1273 | /* no return info, go query for it */ | ||
1274 | kfree(pInfo); | ||
1275 | goto mkdir_get_info; | ||
1276 | } | ||
1277 | /*BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if need | ||
1278 | to set uid/gid */ | ||
1279 | |||
1280 | cifs_unix_basic_to_fattr(&fattr, pInfo, cifs_sb); | ||
1281 | cifs_fill_uniqueid(inode->i_sb, &fattr); | ||
1282 | newinode = cifs_iget(inode->i_sb, &fattr); | ||
1283 | if (!newinode) { | ||
1284 | kfree(pInfo); | ||
1285 | goto mkdir_get_info; | ||
1286 | } | ||
1287 | |||
1288 | d_instantiate(direntry, newinode); | ||
1289 | 1393 | ||
1290 | #ifdef CONFIG_CIFS_DEBUG2 | 1394 | server = tcon->ses->server; |
1291 | cFYI(1, "instantiated dentry %p %s to inode %p", | ||
1292 | direntry, direntry->d_name.name, newinode); | ||
1293 | 1395 | ||
1294 | if (newinode->i_nlink != 2) | 1396 | if (!server->ops->mkdir) { |
1295 | cFYI(1, "unexpected number of links %d", | 1397 | rc = -ENOSYS; |
1296 | newinode->i_nlink); | ||
1297 | #endif | ||
1298 | } | ||
1299 | kfree(pInfo); | ||
1300 | goto mkdir_out; | 1398 | goto mkdir_out; |
1301 | } | 1399 | } |
1302 | mkdir_retry_old: | 1400 | |
1303 | /* BB add setting the equivalent of mode via CreateX w/ACLs */ | 1401 | /* BB add setting the equivalent of mode via CreateX w/ACLs */ |
1304 | rc = CIFSSMBMkDir(xid, tcon, full_path, cifs_sb->local_nls, | 1402 | rc = server->ops->mkdir(xid, tcon, full_path, cifs_sb); |
1305 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
1306 | if (rc) { | 1403 | if (rc) { |
1307 | cFYI(1, "cifs_mkdir returned 0x%x", rc); | 1404 | cFYI(1, "cifs_mkdir returned 0x%x", rc); |
1308 | d_drop(direntry); | 1405 | d_drop(direntry); |
1309 | } else { | 1406 | goto mkdir_out; |
1310 | mkdir_get_info: | ||
1311 | if (tcon->unix_ext) | ||
1312 | rc = cifs_get_inode_info_unix(&newinode, full_path, | ||
1313 | inode->i_sb, xid); | ||
1314 | else | ||
1315 | rc = cifs_get_inode_info(&newinode, full_path, NULL, | ||
1316 | inode->i_sb, xid, NULL); | ||
1317 | |||
1318 | d_instantiate(direntry, newinode); | ||
1319 | /* setting nlink not necessary except in cases where we | ||
1320 | * failed to get it from the server or was set bogus */ | ||
1321 | if ((direntry->d_inode) && (direntry->d_inode->i_nlink < 2)) | ||
1322 | set_nlink(direntry->d_inode, 2); | ||
1323 | |||
1324 | mode &= ~current_umask(); | ||
1325 | /* must turn on setgid bit if parent dir has it */ | ||
1326 | if (inode->i_mode & S_ISGID) | ||
1327 | mode |= S_ISGID; | ||
1328 | |||
1329 | if (tcon->unix_ext) { | ||
1330 | struct cifs_unix_set_info_args args = { | ||
1331 | .mode = mode, | ||
1332 | .ctime = NO_CHANGE_64, | ||
1333 | .atime = NO_CHANGE_64, | ||
1334 | .mtime = NO_CHANGE_64, | ||
1335 | .device = 0, | ||
1336 | }; | ||
1337 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { | ||
1338 | args.uid = (__u64)current_fsuid(); | ||
1339 | if (inode->i_mode & S_ISGID) | ||
1340 | args.gid = (__u64)inode->i_gid; | ||
1341 | else | ||
1342 | args.gid = (__u64)current_fsgid(); | ||
1343 | } else { | ||
1344 | args.uid = NO_CHANGE_64; | ||
1345 | args.gid = NO_CHANGE_64; | ||
1346 | } | ||
1347 | CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args, | ||
1348 | cifs_sb->local_nls, | ||
1349 | cifs_sb->mnt_cifs_flags & | ||
1350 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
1351 | } else { | ||
1352 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) && | ||
1353 | (mode & S_IWUGO) == 0) { | ||
1354 | FILE_BASIC_INFO pInfo; | ||
1355 | struct cifsInodeInfo *cifsInode; | ||
1356 | u32 dosattrs; | ||
1357 | |||
1358 | memset(&pInfo, 0, sizeof(pInfo)); | ||
1359 | cifsInode = CIFS_I(newinode); | ||
1360 | dosattrs = cifsInode->cifsAttrs|ATTR_READONLY; | ||
1361 | pInfo.Attributes = cpu_to_le32(dosattrs); | ||
1362 | tmprc = CIFSSMBSetPathInfo(xid, tcon, | ||
1363 | full_path, &pInfo, | ||
1364 | cifs_sb->local_nls, | ||
1365 | cifs_sb->mnt_cifs_flags & | ||
1366 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
1367 | if (tmprc == 0) | ||
1368 | cifsInode->cifsAttrs = dosattrs; | ||
1369 | } | ||
1370 | if (direntry->d_inode) { | ||
1371 | if (cifs_sb->mnt_cifs_flags & | ||
1372 | CIFS_MOUNT_DYNPERM) | ||
1373 | direntry->d_inode->i_mode = | ||
1374 | (mode | S_IFDIR); | ||
1375 | |||
1376 | if (cifs_sb->mnt_cifs_flags & | ||
1377 | CIFS_MOUNT_SET_UID) { | ||
1378 | direntry->d_inode->i_uid = | ||
1379 | current_fsuid(); | ||
1380 | if (inode->i_mode & S_ISGID) | ||
1381 | direntry->d_inode->i_gid = | ||
1382 | inode->i_gid; | ||
1383 | else | ||
1384 | direntry->d_inode->i_gid = | ||
1385 | current_fsgid(); | ||
1386 | } | ||
1387 | } | ||
1388 | } | ||
1389 | } | 1407 | } |
1408 | |||
1409 | rc = cifs_mkdir_qinfo(inode, direntry, mode, full_path, cifs_sb, tcon, | ||
1410 | xid); | ||
1390 | mkdir_out: | 1411 | mkdir_out: |
1391 | /* | 1412 | /* |
1392 | * Force revalidate to get parent dir info when needed since cached | 1413 | * Force revalidate to get parent dir info when needed since cached |
@@ -1405,7 +1426,8 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry) | |||
1405 | unsigned int xid; | 1426 | unsigned int xid; |
1406 | struct cifs_sb_info *cifs_sb; | 1427 | struct cifs_sb_info *cifs_sb; |
1407 | struct tcon_link *tlink; | 1428 | struct tcon_link *tlink; |
1408 | struct cifs_tcon *pTcon; | 1429 | struct cifs_tcon *tcon; |
1430 | struct TCP_Server_Info *server; | ||
1409 | char *full_path = NULL; | 1431 | char *full_path = NULL; |
1410 | struct cifsInodeInfo *cifsInode; | 1432 | struct cifsInodeInfo *cifsInode; |
1411 | 1433 | ||
@@ -1425,10 +1447,16 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry) | |||
1425 | rc = PTR_ERR(tlink); | 1447 | rc = PTR_ERR(tlink); |
1426 | goto rmdir_exit; | 1448 | goto rmdir_exit; |
1427 | } | 1449 | } |
1428 | pTcon = tlink_tcon(tlink); | 1450 | tcon = tlink_tcon(tlink); |
1451 | server = tcon->ses->server; | ||
1452 | |||
1453 | if (!server->ops->rmdir) { | ||
1454 | rc = -ENOSYS; | ||
1455 | cifs_put_tlink(tlink); | ||
1456 | goto rmdir_exit; | ||
1457 | } | ||
1429 | 1458 | ||
1430 | rc = CIFSSMBRmDir(xid, pTcon, full_path, cifs_sb->local_nls, | 1459 | rc = server->ops->rmdir(xid, tcon, full_path, cifs_sb); |
1431 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
1432 | cifs_put_tlink(tlink); | 1460 | cifs_put_tlink(tlink); |
1433 | 1461 | ||
1434 | if (!rc) { | 1462 | if (!rc) { |
diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c index c40356d24c5..3129ac74b81 100644 --- a/fs/cifs/smb1ops.c +++ b/fs/cifs/smb1ops.c | |||
@@ -586,6 +586,27 @@ cifs_print_stats(struct seq_file *m, struct cifs_tcon *tcon) | |||
586 | #endif | 586 | #endif |
587 | } | 587 | } |
588 | 588 | ||
589 | static void | ||
590 | cifs_mkdir_setinfo(struct inode *inode, const char *full_path, | ||
591 | struct cifs_sb_info *cifs_sb, struct cifs_tcon *tcon, | ||
592 | const unsigned int xid) | ||
593 | { | ||
594 | FILE_BASIC_INFO info; | ||
595 | struct cifsInodeInfo *cifsInode; | ||
596 | u32 dosattrs; | ||
597 | int rc; | ||
598 | |||
599 | memset(&info, 0, sizeof(info)); | ||
600 | cifsInode = CIFS_I(inode); | ||
601 | dosattrs = cifsInode->cifsAttrs|ATTR_READONLY; | ||
602 | info.Attributes = cpu_to_le32(dosattrs); | ||
603 | rc = CIFSSMBSetPathInfo(xid, tcon, full_path, &info, cifs_sb->local_nls, | ||
604 | cifs_sb->mnt_cifs_flags & | ||
605 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
606 | if (rc == 0) | ||
607 | cifsInode->cifsAttrs = dosattrs; | ||
608 | } | ||
609 | |||
589 | struct smb_version_operations smb1_operations = { | 610 | struct smb_version_operations smb1_operations = { |
590 | .send_cancel = send_nt_cancel, | 611 | .send_cancel = send_nt_cancel, |
591 | .compare_fids = cifs_compare_fids, | 612 | .compare_fids = cifs_compare_fids, |
@@ -620,6 +641,9 @@ struct smb_version_operations smb1_operations = { | |||
620 | .get_srv_inum = cifs_get_srv_inum, | 641 | .get_srv_inum = cifs_get_srv_inum, |
621 | .build_path_to_root = cifs_build_path_to_root, | 642 | .build_path_to_root = cifs_build_path_to_root, |
622 | .echo = CIFSSMBEcho, | 643 | .echo = CIFSSMBEcho, |
644 | .mkdir = CIFSSMBMkDir, | ||
645 | .mkdir_setinfo = cifs_mkdir_setinfo, | ||
646 | .rmdir = CIFSSMBRmDir, | ||
623 | }; | 647 | }; |
624 | 648 | ||
625 | struct smb_version_values smb1_values = { | 649 | struct smb_version_values smb1_values = { |
diff --git a/fs/cifs/smb2inode.c b/fs/cifs/smb2inode.c index 1ba5c405315..2aa5cb08c52 100644 --- a/fs/cifs/smb2inode.c +++ b/fs/cifs/smb2inode.c | |||
@@ -122,3 +122,42 @@ out: | |||
122 | kfree(smb2_data); | 122 | kfree(smb2_data); |
123 | return rc; | 123 | return rc; |
124 | } | 124 | } |
125 | |||
126 | int | ||
127 | smb2_mkdir(const unsigned int xid, struct cifs_tcon *tcon, const char *name, | ||
128 | struct cifs_sb_info *cifs_sb) | ||
129 | { | ||
130 | return smb2_open_op_close(xid, tcon, cifs_sb, name, | ||
131 | FILE_WRITE_ATTRIBUTES, FILE_CREATE, 0, | ||
132 | CREATE_NOT_FILE, NULL, SMB2_OP_MKDIR); | ||
133 | } | ||
134 | |||
135 | void | ||
136 | smb2_mkdir_setinfo(struct inode *inode, const char *name, | ||
137 | struct cifs_sb_info *cifs_sb, struct cifs_tcon *tcon, | ||
138 | const unsigned int xid) | ||
139 | { | ||
140 | FILE_BASIC_INFO data; | ||
141 | struct cifsInodeInfo *cifs_i; | ||
142 | u32 dosattrs; | ||
143 | int tmprc; | ||
144 | |||
145 | memset(&data, 0, sizeof(data)); | ||
146 | cifs_i = CIFS_I(inode); | ||
147 | dosattrs = cifs_i->cifsAttrs | ATTR_READONLY; | ||
148 | data.Attributes = cpu_to_le32(dosattrs); | ||
149 | tmprc = smb2_open_op_close(xid, tcon, cifs_sb, name, | ||
150 | FILE_WRITE_ATTRIBUTES, FILE_CREATE, 0, | ||
151 | CREATE_NOT_FILE, &data, SMB2_OP_SET_INFO); | ||
152 | if (tmprc == 0) | ||
153 | cifs_i->cifsAttrs = dosattrs; | ||
154 | } | ||
155 | |||
156 | int | ||
157 | smb2_rmdir(const unsigned int xid, struct cifs_tcon *tcon, const char *name, | ||
158 | struct cifs_sb_info *cifs_sb) | ||
159 | { | ||
160 | return smb2_open_op_close(xid, tcon, cifs_sb, name, DELETE, FILE_OPEN, | ||
161 | 0, CREATE_NOT_FILE | CREATE_DELETE_ON_CLOSE, | ||
162 | NULL, SMB2_OP_DELETE); | ||
163 | } | ||
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index 410cf925ea2..826209bf368 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c | |||
@@ -318,6 +318,9 @@ struct smb_version_operations smb21_operations = { | |||
318 | .query_path_info = smb2_query_path_info, | 318 | .query_path_info = smb2_query_path_info, |
319 | .get_srv_inum = smb2_get_srv_inum, | 319 | .get_srv_inum = smb2_get_srv_inum, |
320 | .build_path_to_root = smb2_build_path_to_root, | 320 | .build_path_to_root = smb2_build_path_to_root, |
321 | .mkdir = smb2_mkdir, | ||
322 | .mkdir_setinfo = smb2_mkdir_setinfo, | ||
323 | .rmdir = smb2_rmdir, | ||
321 | }; | 324 | }; |
322 | 325 | ||
323 | struct smb_version_values smb21_values = { | 326 | struct smb_version_values smb21_values = { |
diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h index 902bbe2b5ad..bfaa7b148af 100644 --- a/fs/cifs/smb2proto.h +++ b/fs/cifs/smb2proto.h | |||
@@ -52,6 +52,14 @@ extern int smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon, | |||
52 | struct cifs_sb_info *cifs_sb, | 52 | struct cifs_sb_info *cifs_sb, |
53 | const char *full_path, FILE_ALL_INFO *data, | 53 | const char *full_path, FILE_ALL_INFO *data, |
54 | bool *adjust_tz); | 54 | bool *adjust_tz); |
55 | extern int smb2_mkdir(const unsigned int xid, struct cifs_tcon *tcon, | ||
56 | const char *name, struct cifs_sb_info *cifs_sb); | ||
57 | extern void smb2_mkdir_setinfo(struct inode *inode, const char *full_path, | ||
58 | struct cifs_sb_info *cifs_sb, | ||
59 | struct cifs_tcon *tcon, const unsigned int xid); | ||
60 | extern int smb2_rmdir(const unsigned int xid, struct cifs_tcon *tcon, | ||
61 | const char *name, struct cifs_sb_info *cifs_sb); | ||
62 | |||
55 | /* | 63 | /* |
56 | * SMB2 Worker functions - most of protocol specific implementation details | 64 | * SMB2 Worker functions - most of protocol specific implementation details |
57 | * are contained within these calls. | 65 | * are contained within these calls. |
diff --git a/fs/compat.c b/fs/compat.c index 6161255fac4..1bdb350ea5d 100644 --- a/fs/compat.c +++ b/fs/compat.c | |||
@@ -1155,11 +1155,14 @@ compat_sys_readv(unsigned long fd, const struct compat_iovec __user *vec, | |||
1155 | struct file *file; | 1155 | struct file *file; |
1156 | int fput_needed; | 1156 | int fput_needed; |
1157 | ssize_t ret; | 1157 | ssize_t ret; |
1158 | loff_t pos; | ||
1158 | 1159 | ||
1159 | file = fget_light(fd, &fput_needed); | 1160 | file = fget_light(fd, &fput_needed); |
1160 | if (!file) | 1161 | if (!file) |
1161 | return -EBADF; | 1162 | return -EBADF; |
1162 | ret = compat_readv(file, vec, vlen, &file->f_pos); | 1163 | pos = file->f_pos; |
1164 | ret = compat_readv(file, vec, vlen, &pos); | ||
1165 | file->f_pos = pos; | ||
1163 | fput_light(file, fput_needed); | 1166 | fput_light(file, fput_needed); |
1164 | return ret; | 1167 | return ret; |
1165 | } | 1168 | } |
@@ -1221,11 +1224,14 @@ compat_sys_writev(unsigned long fd, const struct compat_iovec __user *vec, | |||
1221 | struct file *file; | 1224 | struct file *file; |
1222 | int fput_needed; | 1225 | int fput_needed; |
1223 | ssize_t ret; | 1226 | ssize_t ret; |
1227 | loff_t pos; | ||
1224 | 1228 | ||
1225 | file = fget_light(fd, &fput_needed); | 1229 | file = fget_light(fd, &fput_needed); |
1226 | if (!file) | 1230 | if (!file) |
1227 | return -EBADF; | 1231 | return -EBADF; |
1228 | ret = compat_writev(file, vec, vlen, &file->f_pos); | 1232 | pos = file->f_pos; |
1233 | ret = compat_writev(file, vec, vlen, &pos); | ||
1234 | file->f_pos = pos; | ||
1229 | fput_light(file, fput_needed); | 1235 | fput_light(file, fput_needed); |
1230 | return ret; | 1236 | return ret; |
1231 | } | 1237 | } |
diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h index 989e034f02b..cfb4b9fed52 100644 --- a/fs/ecryptfs/ecryptfs_kernel.h +++ b/fs/ecryptfs/ecryptfs_kernel.h | |||
@@ -385,8 +385,6 @@ struct ecryptfs_msg_ctx { | |||
385 | struct mutex mux; | 385 | struct mutex mux; |
386 | }; | 386 | }; |
387 | 387 | ||
388 | struct ecryptfs_daemon; | ||
389 | |||
390 | struct ecryptfs_daemon { | 388 | struct ecryptfs_daemon { |
391 | #define ECRYPTFS_DAEMON_IN_READ 0x00000001 | 389 | #define ECRYPTFS_DAEMON_IN_READ 0x00000001 |
392 | #define ECRYPTFS_DAEMON_IN_POLL 0x00000002 | 390 | #define ECRYPTFS_DAEMON_IN_POLL 0x00000002 |
@@ -394,10 +392,7 @@ struct ecryptfs_daemon { | |||
394 | #define ECRYPTFS_DAEMON_MISCDEV_OPEN 0x00000008 | 392 | #define ECRYPTFS_DAEMON_MISCDEV_OPEN 0x00000008 |
395 | u32 flags; | 393 | u32 flags; |
396 | u32 num_queued_msg_ctx; | 394 | u32 num_queued_msg_ctx; |
397 | struct pid *pid; | 395 | struct file *file; |
398 | uid_t euid; | ||
399 | struct user_namespace *user_ns; | ||
400 | struct task_struct *task; | ||
401 | struct mutex mux; | 396 | struct mutex mux; |
402 | struct list_head msg_ctx_out_queue; | 397 | struct list_head msg_ctx_out_queue; |
403 | wait_queue_head_t wait; | 398 | wait_queue_head_t wait; |
@@ -554,6 +549,8 @@ extern struct kmem_cache *ecryptfs_key_tfm_cache; | |||
554 | struct inode *ecryptfs_get_inode(struct inode *lower_inode, | 549 | struct inode *ecryptfs_get_inode(struct inode *lower_inode, |
555 | struct super_block *sb); | 550 | struct super_block *sb); |
556 | void ecryptfs_i_size_init(const char *page_virt, struct inode *inode); | 551 | void ecryptfs_i_size_init(const char *page_virt, struct inode *inode); |
552 | int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry, | ||
553 | struct inode *ecryptfs_inode); | ||
557 | int ecryptfs_decode_and_decrypt_filename(char **decrypted_name, | 554 | int ecryptfs_decode_and_decrypt_filename(char **decrypted_name, |
558 | size_t *decrypted_name_size, | 555 | size_t *decrypted_name_size, |
559 | struct dentry *ecryptfs_dentry, | 556 | struct dentry *ecryptfs_dentry, |
@@ -607,13 +604,8 @@ int | |||
607 | ecryptfs_setxattr(struct dentry *dentry, const char *name, const void *value, | 604 | ecryptfs_setxattr(struct dentry *dentry, const char *name, const void *value, |
608 | size_t size, int flags); | 605 | size_t size, int flags); |
609 | int ecryptfs_read_xattr_region(char *page_virt, struct inode *ecryptfs_inode); | 606 | int ecryptfs_read_xattr_region(char *page_virt, struct inode *ecryptfs_inode); |
610 | int ecryptfs_process_helo(uid_t euid, struct user_namespace *user_ns, | 607 | int ecryptfs_process_response(struct ecryptfs_daemon *daemon, |
611 | struct pid *pid); | 608 | struct ecryptfs_message *msg, u32 seq); |
612 | int ecryptfs_process_quit(uid_t euid, struct user_namespace *user_ns, | ||
613 | struct pid *pid); | ||
614 | int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t euid, | ||
615 | struct user_namespace *user_ns, struct pid *pid, | ||
616 | u32 seq); | ||
617 | int ecryptfs_send_message(char *data, int data_len, | 609 | int ecryptfs_send_message(char *data, int data_len, |
618 | struct ecryptfs_msg_ctx **msg_ctx); | 610 | struct ecryptfs_msg_ctx **msg_ctx); |
619 | int ecryptfs_wait_for_response(struct ecryptfs_msg_ctx *msg_ctx, | 611 | int ecryptfs_wait_for_response(struct ecryptfs_msg_ctx *msg_ctx, |
@@ -658,8 +650,7 @@ int ecryptfs_read_lower_page_segment(struct page *page_for_ecryptfs, | |||
658 | struct inode *ecryptfs_inode); | 650 | struct inode *ecryptfs_inode); |
659 | struct page *ecryptfs_get_locked_page(struct inode *inode, loff_t index); | 651 | struct page *ecryptfs_get_locked_page(struct inode *inode, loff_t index); |
660 | int ecryptfs_exorcise_daemon(struct ecryptfs_daemon *daemon); | 652 | int ecryptfs_exorcise_daemon(struct ecryptfs_daemon *daemon); |
661 | int ecryptfs_find_daemon_by_euid(struct ecryptfs_daemon **daemon, uid_t euid, | 653 | int ecryptfs_find_daemon_by_euid(struct ecryptfs_daemon **daemon); |
662 | struct user_namespace *user_ns); | ||
663 | int ecryptfs_parse_packet_length(unsigned char *data, size_t *size, | 654 | int ecryptfs_parse_packet_length(unsigned char *data, size_t *size, |
664 | size_t *length_size); | 655 | size_t *length_size); |
665 | int ecryptfs_write_packet_length(char *dest, size_t size, | 656 | int ecryptfs_write_packet_length(char *dest, size_t size, |
@@ -671,8 +662,7 @@ int ecryptfs_send_miscdev(char *data, size_t data_size, | |||
671 | u16 msg_flags, struct ecryptfs_daemon *daemon); | 662 | u16 msg_flags, struct ecryptfs_daemon *daemon); |
672 | void ecryptfs_msg_ctx_alloc_to_free(struct ecryptfs_msg_ctx *msg_ctx); | 663 | void ecryptfs_msg_ctx_alloc_to_free(struct ecryptfs_msg_ctx *msg_ctx); |
673 | int | 664 | int |
674 | ecryptfs_spawn_daemon(struct ecryptfs_daemon **daemon, uid_t euid, | 665 | ecryptfs_spawn_daemon(struct ecryptfs_daemon **daemon, struct file *file); |
675 | struct user_namespace *user_ns, struct pid *pid); | ||
676 | int ecryptfs_init_kthread(void); | 666 | int ecryptfs_init_kthread(void); |
677 | void ecryptfs_destroy_kthread(void); | 667 | void ecryptfs_destroy_kthread(void); |
678 | int ecryptfs_privileged_open(struct file **lower_file, | 668 | int ecryptfs_privileged_open(struct file **lower_file, |
diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c index 2b17f2f9b12..44ce5c6a541 100644 --- a/fs/ecryptfs/file.c +++ b/fs/ecryptfs/file.c | |||
@@ -138,29 +138,50 @@ out: | |||
138 | return rc; | 138 | return rc; |
139 | } | 139 | } |
140 | 140 | ||
141 | static void ecryptfs_vma_close(struct vm_area_struct *vma) | 141 | struct kmem_cache *ecryptfs_file_info_cache; |
142 | { | ||
143 | filemap_write_and_wait(vma->vm_file->f_mapping); | ||
144 | } | ||
145 | |||
146 | static const struct vm_operations_struct ecryptfs_file_vm_ops = { | ||
147 | .close = ecryptfs_vma_close, | ||
148 | .fault = filemap_fault, | ||
149 | }; | ||
150 | 142 | ||
151 | static int ecryptfs_file_mmap(struct file *file, struct vm_area_struct *vma) | 143 | static int read_or_initialize_metadata(struct dentry *dentry) |
152 | { | 144 | { |
145 | struct inode *inode = dentry->d_inode; | ||
146 | struct ecryptfs_mount_crypt_stat *mount_crypt_stat; | ||
147 | struct ecryptfs_crypt_stat *crypt_stat; | ||
153 | int rc; | 148 | int rc; |
154 | 149 | ||
155 | rc = generic_file_mmap(file, vma); | 150 | crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat; |
151 | mount_crypt_stat = &ecryptfs_superblock_to_private( | ||
152 | inode->i_sb)->mount_crypt_stat; | ||
153 | mutex_lock(&crypt_stat->cs_mutex); | ||
154 | |||
155 | if (crypt_stat->flags & ECRYPTFS_POLICY_APPLIED && | ||
156 | crypt_stat->flags & ECRYPTFS_KEY_VALID) { | ||
157 | rc = 0; | ||
158 | goto out; | ||
159 | } | ||
160 | |||
161 | rc = ecryptfs_read_metadata(dentry); | ||
156 | if (!rc) | 162 | if (!rc) |
157 | vma->vm_ops = &ecryptfs_file_vm_ops; | 163 | goto out; |
164 | |||
165 | if (mount_crypt_stat->flags & ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED) { | ||
166 | crypt_stat->flags &= ~(ECRYPTFS_I_SIZE_INITIALIZED | ||
167 | | ECRYPTFS_ENCRYPTED); | ||
168 | rc = 0; | ||
169 | goto out; | ||
170 | } | ||
158 | 171 | ||
172 | if (!(mount_crypt_stat->flags & ECRYPTFS_XATTR_METADATA_ENABLED) && | ||
173 | !i_size_read(ecryptfs_inode_to_lower(inode))) { | ||
174 | rc = ecryptfs_initialize_file(dentry, inode); | ||
175 | if (!rc) | ||
176 | goto out; | ||
177 | } | ||
178 | |||
179 | rc = -EIO; | ||
180 | out: | ||
181 | mutex_unlock(&crypt_stat->cs_mutex); | ||
159 | return rc; | 182 | return rc; |
160 | } | 183 | } |
161 | 184 | ||
162 | struct kmem_cache *ecryptfs_file_info_cache; | ||
163 | |||
164 | /** | 185 | /** |
165 | * ecryptfs_open | 186 | * ecryptfs_open |
166 | * @inode: inode speciying file to open | 187 | * @inode: inode speciying file to open |
@@ -236,32 +257,9 @@ static int ecryptfs_open(struct inode *inode, struct file *file) | |||
236 | rc = 0; | 257 | rc = 0; |
237 | goto out; | 258 | goto out; |
238 | } | 259 | } |
239 | mutex_lock(&crypt_stat->cs_mutex); | 260 | rc = read_or_initialize_metadata(ecryptfs_dentry); |
240 | if (!(crypt_stat->flags & ECRYPTFS_POLICY_APPLIED) | 261 | if (rc) |
241 | || !(crypt_stat->flags & ECRYPTFS_KEY_VALID)) { | 262 | goto out_put; |
242 | rc = ecryptfs_read_metadata(ecryptfs_dentry); | ||
243 | if (rc) { | ||
244 | ecryptfs_printk(KERN_DEBUG, | ||
245 | "Valid headers not found\n"); | ||
246 | if (!(mount_crypt_stat->flags | ||
247 | & ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED)) { | ||
248 | rc = -EIO; | ||
249 | printk(KERN_WARNING "Either the lower file " | ||
250 | "is not in a valid eCryptfs format, " | ||
251 | "or the key could not be retrieved. " | ||
252 | "Plaintext passthrough mode is not " | ||
253 | "enabled; returning -EIO\n"); | ||
254 | mutex_unlock(&crypt_stat->cs_mutex); | ||
255 | goto out_put; | ||
256 | } | ||
257 | rc = 0; | ||
258 | crypt_stat->flags &= ~(ECRYPTFS_I_SIZE_INITIALIZED | ||
259 | | ECRYPTFS_ENCRYPTED); | ||
260 | mutex_unlock(&crypt_stat->cs_mutex); | ||
261 | goto out; | ||
262 | } | ||
263 | } | ||
264 | mutex_unlock(&crypt_stat->cs_mutex); | ||
265 | ecryptfs_printk(KERN_DEBUG, "inode w/ addr = [0x%p], i_ino = " | 263 | ecryptfs_printk(KERN_DEBUG, "inode w/ addr = [0x%p], i_ino = " |
266 | "[0x%.16lx] size: [0x%.16llx]\n", inode, inode->i_ino, | 264 | "[0x%.16lx] size: [0x%.16llx]\n", inode, inode->i_ino, |
267 | (unsigned long long)i_size_read(inode)); | 265 | (unsigned long long)i_size_read(inode)); |
@@ -292,15 +290,7 @@ static int ecryptfs_release(struct inode *inode, struct file *file) | |||
292 | static int | 290 | static int |
293 | ecryptfs_fsync(struct file *file, loff_t start, loff_t end, int datasync) | 291 | ecryptfs_fsync(struct file *file, loff_t start, loff_t end, int datasync) |
294 | { | 292 | { |
295 | int rc = 0; | 293 | return vfs_fsync(ecryptfs_file_to_lower(file), datasync); |
296 | |||
297 | rc = generic_file_fsync(file, start, end, datasync); | ||
298 | if (rc) | ||
299 | goto out; | ||
300 | rc = vfs_fsync_range(ecryptfs_file_to_lower(file), start, end, | ||
301 | datasync); | ||
302 | out: | ||
303 | return rc; | ||
304 | } | 294 | } |
305 | 295 | ||
306 | static int ecryptfs_fasync(int fd, struct file *file, int flag) | 296 | static int ecryptfs_fasync(int fd, struct file *file, int flag) |
@@ -369,7 +359,7 @@ const struct file_operations ecryptfs_main_fops = { | |||
369 | #ifdef CONFIG_COMPAT | 359 | #ifdef CONFIG_COMPAT |
370 | .compat_ioctl = ecryptfs_compat_ioctl, | 360 | .compat_ioctl = ecryptfs_compat_ioctl, |
371 | #endif | 361 | #endif |
372 | .mmap = ecryptfs_file_mmap, | 362 | .mmap = generic_file_mmap, |
373 | .open = ecryptfs_open, | 363 | .open = ecryptfs_open, |
374 | .flush = ecryptfs_flush, | 364 | .flush = ecryptfs_flush, |
375 | .release = ecryptfs_release, | 365 | .release = ecryptfs_release, |
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index c3ca12c33ca..534b129ea67 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c | |||
@@ -143,6 +143,31 @@ static int ecryptfs_interpose(struct dentry *lower_dentry, | |||
143 | return 0; | 143 | return 0; |
144 | } | 144 | } |
145 | 145 | ||
146 | static int ecryptfs_do_unlink(struct inode *dir, struct dentry *dentry, | ||
147 | struct inode *inode) | ||
148 | { | ||
149 | struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry); | ||
150 | struct inode *lower_dir_inode = ecryptfs_inode_to_lower(dir); | ||
151 | struct dentry *lower_dir_dentry; | ||
152 | int rc; | ||
153 | |||
154 | dget(lower_dentry); | ||
155 | lower_dir_dentry = lock_parent(lower_dentry); | ||
156 | rc = vfs_unlink(lower_dir_inode, lower_dentry); | ||
157 | if (rc) { | ||
158 | printk(KERN_ERR "Error in vfs_unlink; rc = [%d]\n", rc); | ||
159 | goto out_unlock; | ||
160 | } | ||
161 | fsstack_copy_attr_times(dir, lower_dir_inode); | ||
162 | set_nlink(inode, ecryptfs_inode_to_lower(inode)->i_nlink); | ||
163 | inode->i_ctime = dir->i_ctime; | ||
164 | d_drop(dentry); | ||
165 | out_unlock: | ||
166 | unlock_dir(lower_dir_dentry); | ||
167 | dput(lower_dentry); | ||
168 | return rc; | ||
169 | } | ||
170 | |||
146 | /** | 171 | /** |
147 | * ecryptfs_do_create | 172 | * ecryptfs_do_create |
148 | * @directory_inode: inode of the new file's dentry's parent in ecryptfs | 173 | * @directory_inode: inode of the new file's dentry's parent in ecryptfs |
@@ -182,8 +207,10 @@ ecryptfs_do_create(struct inode *directory_inode, | |||
182 | } | 207 | } |
183 | inode = __ecryptfs_get_inode(lower_dentry->d_inode, | 208 | inode = __ecryptfs_get_inode(lower_dentry->d_inode, |
184 | directory_inode->i_sb); | 209 | directory_inode->i_sb); |
185 | if (IS_ERR(inode)) | 210 | if (IS_ERR(inode)) { |
211 | vfs_unlink(lower_dir_dentry->d_inode, lower_dentry); | ||
186 | goto out_lock; | 212 | goto out_lock; |
213 | } | ||
187 | fsstack_copy_attr_times(directory_inode, lower_dir_dentry->d_inode); | 214 | fsstack_copy_attr_times(directory_inode, lower_dir_dentry->d_inode); |
188 | fsstack_copy_inode_size(directory_inode, lower_dir_dentry->d_inode); | 215 | fsstack_copy_inode_size(directory_inode, lower_dir_dentry->d_inode); |
189 | out_lock: | 216 | out_lock: |
@@ -200,8 +227,8 @@ out: | |||
200 | * | 227 | * |
201 | * Returns zero on success | 228 | * Returns zero on success |
202 | */ | 229 | */ |
203 | static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry, | 230 | int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry, |
204 | struct inode *ecryptfs_inode) | 231 | struct inode *ecryptfs_inode) |
205 | { | 232 | { |
206 | struct ecryptfs_crypt_stat *crypt_stat = | 233 | struct ecryptfs_crypt_stat *crypt_stat = |
207 | &ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat; | 234 | &ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat; |
@@ -264,7 +291,9 @@ ecryptfs_create(struct inode *directory_inode, struct dentry *ecryptfs_dentry, | |||
264 | * that this on disk file is prepared to be an ecryptfs file */ | 291 | * that this on disk file is prepared to be an ecryptfs file */ |
265 | rc = ecryptfs_initialize_file(ecryptfs_dentry, ecryptfs_inode); | 292 | rc = ecryptfs_initialize_file(ecryptfs_dentry, ecryptfs_inode); |
266 | if (rc) { | 293 | if (rc) { |
267 | drop_nlink(ecryptfs_inode); | 294 | ecryptfs_do_unlink(directory_inode, ecryptfs_dentry, |
295 | ecryptfs_inode); | ||
296 | make_bad_inode(ecryptfs_inode); | ||
268 | unlock_new_inode(ecryptfs_inode); | 297 | unlock_new_inode(ecryptfs_inode); |
269 | iput(ecryptfs_inode); | 298 | iput(ecryptfs_inode); |
270 | goto out; | 299 | goto out; |
@@ -466,27 +495,7 @@ out_lock: | |||
466 | 495 | ||
467 | static int ecryptfs_unlink(struct inode *dir, struct dentry *dentry) | 496 | static int ecryptfs_unlink(struct inode *dir, struct dentry *dentry) |
468 | { | 497 | { |
469 | int rc = 0; | 498 | return ecryptfs_do_unlink(dir, dentry, dentry->d_inode); |
470 | struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry); | ||
471 | struct inode *lower_dir_inode = ecryptfs_inode_to_lower(dir); | ||
472 | struct dentry *lower_dir_dentry; | ||
473 | |||
474 | dget(lower_dentry); | ||
475 | lower_dir_dentry = lock_parent(lower_dentry); | ||
476 | rc = vfs_unlink(lower_dir_inode, lower_dentry); | ||
477 | if (rc) { | ||
478 | printk(KERN_ERR "Error in vfs_unlink; rc = [%d]\n", rc); | ||
479 | goto out_unlock; | ||
480 | } | ||
481 | fsstack_copy_attr_times(dir, lower_dir_inode); | ||
482 | set_nlink(dentry->d_inode, | ||
483 | ecryptfs_inode_to_lower(dentry->d_inode)->i_nlink); | ||
484 | dentry->d_inode->i_ctime = dir->i_ctime; | ||
485 | d_drop(dentry); | ||
486 | out_unlock: | ||
487 | unlock_dir(lower_dir_dentry); | ||
488 | dput(lower_dentry); | ||
489 | return rc; | ||
490 | } | 499 | } |
491 | 500 | ||
492 | static int ecryptfs_symlink(struct inode *dir, struct dentry *dentry, | 501 | static int ecryptfs_symlink(struct inode *dir, struct dentry *dentry, |
@@ -961,12 +970,6 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia) | |||
961 | goto out; | 970 | goto out; |
962 | } | 971 | } |
963 | 972 | ||
964 | if (S_ISREG(inode->i_mode)) { | ||
965 | rc = filemap_write_and_wait(inode->i_mapping); | ||
966 | if (rc) | ||
967 | goto out; | ||
968 | fsstack_copy_attr_all(inode, lower_inode); | ||
969 | } | ||
970 | memcpy(&lower_ia, ia, sizeof(lower_ia)); | 973 | memcpy(&lower_ia, ia, sizeof(lower_ia)); |
971 | if (ia->ia_valid & ATTR_FILE) | 974 | if (ia->ia_valid & ATTR_FILE) |
972 | lower_ia.ia_file = ecryptfs_file_to_lower(ia->ia_file); | 975 | lower_ia.ia_file = ecryptfs_file_to_lower(ia->ia_file); |
diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c index 1c0b3b6b75c..2768138eefe 100644 --- a/fs/ecryptfs/main.c +++ b/fs/ecryptfs/main.c | |||
@@ -279,6 +279,7 @@ static int ecryptfs_parse_options(struct ecryptfs_sb_info *sbi, char *options, | |||
279 | char *fnek_src; | 279 | char *fnek_src; |
280 | char *cipher_key_bytes_src; | 280 | char *cipher_key_bytes_src; |
281 | char *fn_cipher_key_bytes_src; | 281 | char *fn_cipher_key_bytes_src; |
282 | u8 cipher_code; | ||
282 | 283 | ||
283 | *check_ruid = 0; | 284 | *check_ruid = 0; |
284 | 285 | ||
@@ -420,6 +421,18 @@ static int ecryptfs_parse_options(struct ecryptfs_sb_info *sbi, char *options, | |||
420 | && !fn_cipher_key_bytes_set) | 421 | && !fn_cipher_key_bytes_set) |
421 | mount_crypt_stat->global_default_fn_cipher_key_bytes = | 422 | mount_crypt_stat->global_default_fn_cipher_key_bytes = |
422 | mount_crypt_stat->global_default_cipher_key_size; | 423 | mount_crypt_stat->global_default_cipher_key_size; |
424 | |||
425 | cipher_code = ecryptfs_code_for_cipher_string( | ||
426 | mount_crypt_stat->global_default_cipher_name, | ||
427 | mount_crypt_stat->global_default_cipher_key_size); | ||
428 | if (!cipher_code) { | ||
429 | ecryptfs_printk(KERN_ERR, | ||
430 | "eCryptfs doesn't support cipher: %s", | ||
431 | mount_crypt_stat->global_default_cipher_name); | ||
432 | rc = -EINVAL; | ||
433 | goto out; | ||
434 | } | ||
435 | |||
423 | mutex_lock(&key_tfm_list_mutex); | 436 | mutex_lock(&key_tfm_list_mutex); |
424 | if (!ecryptfs_tfm_exists(mount_crypt_stat->global_default_cipher_name, | 437 | if (!ecryptfs_tfm_exists(mount_crypt_stat->global_default_cipher_name, |
425 | NULL)) { | 438 | NULL)) { |
@@ -540,6 +553,15 @@ static struct dentry *ecryptfs_mount(struct file_system_type *fs_type, int flags | |||
540 | } | 553 | } |
541 | 554 | ||
542 | ecryptfs_set_superblock_lower(s, path.dentry->d_sb); | 555 | ecryptfs_set_superblock_lower(s, path.dentry->d_sb); |
556 | |||
557 | /** | ||
558 | * Set the POSIX ACL flag based on whether they're enabled in the lower | ||
559 | * mount. Force a read-only eCryptfs mount if the lower mount is ro. | ||
560 | * Allow a ro eCryptfs mount even when the lower mount is rw. | ||
561 | */ | ||
562 | s->s_flags = flags & ~MS_POSIXACL; | ||
563 | s->s_flags |= path.dentry->d_sb->s_flags & (MS_RDONLY | MS_POSIXACL); | ||
564 | |||
543 | s->s_maxbytes = path.dentry->d_sb->s_maxbytes; | 565 | s->s_maxbytes = path.dentry->d_sb->s_maxbytes; |
544 | s->s_blocksize = path.dentry->d_sb->s_blocksize; | 566 | s->s_blocksize = path.dentry->d_sb->s_blocksize; |
545 | s->s_magic = ECRYPTFS_SUPER_MAGIC; | 567 | s->s_magic = ECRYPTFS_SUPER_MAGIC; |
diff --git a/fs/ecryptfs/messaging.c b/fs/ecryptfs/messaging.c index a750f957b14..b29bb8bfa8d 100644 --- a/fs/ecryptfs/messaging.c +++ b/fs/ecryptfs/messaging.c | |||
@@ -32,8 +32,8 @@ static struct mutex ecryptfs_msg_ctx_lists_mux; | |||
32 | static struct hlist_head *ecryptfs_daemon_hash; | 32 | static struct hlist_head *ecryptfs_daemon_hash; |
33 | struct mutex ecryptfs_daemon_hash_mux; | 33 | struct mutex ecryptfs_daemon_hash_mux; |
34 | static int ecryptfs_hash_bits; | 34 | static int ecryptfs_hash_bits; |
35 | #define ecryptfs_uid_hash(uid) \ | 35 | #define ecryptfs_current_euid_hash(uid) \ |
36 | hash_long((unsigned long)uid, ecryptfs_hash_bits) | 36 | hash_long((unsigned long)current_euid(), ecryptfs_hash_bits) |
37 | 37 | ||
38 | static u32 ecryptfs_msg_counter; | 38 | static u32 ecryptfs_msg_counter; |
39 | static struct ecryptfs_msg_ctx *ecryptfs_msg_ctx_arr; | 39 | static struct ecryptfs_msg_ctx *ecryptfs_msg_ctx_arr; |
@@ -105,26 +105,24 @@ void ecryptfs_msg_ctx_alloc_to_free(struct ecryptfs_msg_ctx *msg_ctx) | |||
105 | 105 | ||
106 | /** | 106 | /** |
107 | * ecryptfs_find_daemon_by_euid | 107 | * ecryptfs_find_daemon_by_euid |
108 | * @euid: The effective user id which maps to the desired daemon id | ||
109 | * @user_ns: The namespace in which @euid applies | ||
110 | * @daemon: If return value is zero, points to the desired daemon pointer | 108 | * @daemon: If return value is zero, points to the desired daemon pointer |
111 | * | 109 | * |
112 | * Must be called with ecryptfs_daemon_hash_mux held. | 110 | * Must be called with ecryptfs_daemon_hash_mux held. |
113 | * | 111 | * |
114 | * Search the hash list for the given user id. | 112 | * Search the hash list for the current effective user id. |
115 | * | 113 | * |
116 | * Returns zero if the user id exists in the list; non-zero otherwise. | 114 | * Returns zero if the user id exists in the list; non-zero otherwise. |
117 | */ | 115 | */ |
118 | int ecryptfs_find_daemon_by_euid(struct ecryptfs_daemon **daemon, uid_t euid, | 116 | int ecryptfs_find_daemon_by_euid(struct ecryptfs_daemon **daemon) |
119 | struct user_namespace *user_ns) | ||
120 | { | 117 | { |
121 | struct hlist_node *elem; | 118 | struct hlist_node *elem; |
122 | int rc; | 119 | int rc; |
123 | 120 | ||
124 | hlist_for_each_entry(*daemon, elem, | 121 | hlist_for_each_entry(*daemon, elem, |
125 | &ecryptfs_daemon_hash[ecryptfs_uid_hash(euid)], | 122 | &ecryptfs_daemon_hash[ecryptfs_current_euid_hash()], |
126 | euid_chain) { | 123 | euid_chain) { |
127 | if ((*daemon)->euid == euid && (*daemon)->user_ns == user_ns) { | 124 | if ((*daemon)->file->f_cred->euid == current_euid() && |
125 | (*daemon)->file->f_cred->user_ns == current_user_ns()) { | ||
128 | rc = 0; | 126 | rc = 0; |
129 | goto out; | 127 | goto out; |
130 | } | 128 | } |
@@ -137,9 +135,7 @@ out: | |||
137 | /** | 135 | /** |
138 | * ecryptfs_spawn_daemon - Create and initialize a new daemon struct | 136 | * ecryptfs_spawn_daemon - Create and initialize a new daemon struct |
139 | * @daemon: Pointer to set to newly allocated daemon struct | 137 | * @daemon: Pointer to set to newly allocated daemon struct |
140 | * @euid: Effective user id for the daemon | 138 | * @file: File used when opening /dev/ecryptfs |
141 | * @user_ns: The namespace in which @euid applies | ||
142 | * @pid: Process id for the daemon | ||
143 | * | 139 | * |
144 | * Must be called ceremoniously while in possession of | 140 | * Must be called ceremoniously while in possession of |
145 | * ecryptfs_sacred_daemon_hash_mux | 141 | * ecryptfs_sacred_daemon_hash_mux |
@@ -147,8 +143,7 @@ out: | |||
147 | * Returns zero on success; non-zero otherwise | 143 | * Returns zero on success; non-zero otherwise |
148 | */ | 144 | */ |
149 | int | 145 | int |
150 | ecryptfs_spawn_daemon(struct ecryptfs_daemon **daemon, uid_t euid, | 146 | ecryptfs_spawn_daemon(struct ecryptfs_daemon **daemon, struct file *file) |
151 | struct user_namespace *user_ns, struct pid *pid) | ||
152 | { | 147 | { |
153 | int rc = 0; | 148 | int rc = 0; |
154 | 149 | ||
@@ -159,16 +154,13 @@ ecryptfs_spawn_daemon(struct ecryptfs_daemon **daemon, uid_t euid, | |||
159 | "GFP_KERNEL memory\n", __func__, sizeof(**daemon)); | 154 | "GFP_KERNEL memory\n", __func__, sizeof(**daemon)); |
160 | goto out; | 155 | goto out; |
161 | } | 156 | } |
162 | (*daemon)->euid = euid; | 157 | (*daemon)->file = file; |
163 | (*daemon)->user_ns = get_user_ns(user_ns); | ||
164 | (*daemon)->pid = get_pid(pid); | ||
165 | (*daemon)->task = current; | ||
166 | mutex_init(&(*daemon)->mux); | 158 | mutex_init(&(*daemon)->mux); |
167 | INIT_LIST_HEAD(&(*daemon)->msg_ctx_out_queue); | 159 | INIT_LIST_HEAD(&(*daemon)->msg_ctx_out_queue); |
168 | init_waitqueue_head(&(*daemon)->wait); | 160 | init_waitqueue_head(&(*daemon)->wait); |
169 | (*daemon)->num_queued_msg_ctx = 0; | 161 | (*daemon)->num_queued_msg_ctx = 0; |
170 | hlist_add_head(&(*daemon)->euid_chain, | 162 | hlist_add_head(&(*daemon)->euid_chain, |
171 | &ecryptfs_daemon_hash[ecryptfs_uid_hash(euid)]); | 163 | &ecryptfs_daemon_hash[ecryptfs_current_euid_hash()]); |
172 | out: | 164 | out: |
173 | return rc; | 165 | return rc; |
174 | } | 166 | } |
@@ -188,9 +180,6 @@ int ecryptfs_exorcise_daemon(struct ecryptfs_daemon *daemon) | |||
188 | if ((daemon->flags & ECRYPTFS_DAEMON_IN_READ) | 180 | if ((daemon->flags & ECRYPTFS_DAEMON_IN_READ) |
189 | || (daemon->flags & ECRYPTFS_DAEMON_IN_POLL)) { | 181 | || (daemon->flags & ECRYPTFS_DAEMON_IN_POLL)) { |
190 | rc = -EBUSY; | 182 | rc = -EBUSY; |
191 | printk(KERN_WARNING "%s: Attempt to destroy daemon with pid " | ||
192 | "[0x%p], but it is in the midst of a read or a poll\n", | ||
193 | __func__, daemon->pid); | ||
194 | mutex_unlock(&daemon->mux); | 183 | mutex_unlock(&daemon->mux); |
195 | goto out; | 184 | goto out; |
196 | } | 185 | } |
@@ -203,12 +192,6 @@ int ecryptfs_exorcise_daemon(struct ecryptfs_daemon *daemon) | |||
203 | ecryptfs_msg_ctx_alloc_to_free(msg_ctx); | 192 | ecryptfs_msg_ctx_alloc_to_free(msg_ctx); |
204 | } | 193 | } |
205 | hlist_del(&daemon->euid_chain); | 194 | hlist_del(&daemon->euid_chain); |
206 | if (daemon->task) | ||
207 | wake_up_process(daemon->task); | ||
208 | if (daemon->pid) | ||
209 | put_pid(daemon->pid); | ||
210 | if (daemon->user_ns) | ||
211 | put_user_ns(daemon->user_ns); | ||
212 | mutex_unlock(&daemon->mux); | 195 | mutex_unlock(&daemon->mux); |
213 | kzfree(daemon); | 196 | kzfree(daemon); |
214 | out: | 197 | out: |
@@ -216,42 +199,9 @@ out: | |||
216 | } | 199 | } |
217 | 200 | ||
218 | /** | 201 | /** |
219 | * ecryptfs_process_quit | ||
220 | * @euid: The user ID owner of the message | ||
221 | * @user_ns: The namespace in which @euid applies | ||
222 | * @pid: The process ID for the userspace program that sent the | ||
223 | * message | ||
224 | * | ||
225 | * Deletes the corresponding daemon for the given euid and pid, if | ||
226 | * it is the registered that is requesting the deletion. Returns zero | ||
227 | * after deleting the desired daemon; non-zero otherwise. | ||
228 | */ | ||
229 | int ecryptfs_process_quit(uid_t euid, struct user_namespace *user_ns, | ||
230 | struct pid *pid) | ||
231 | { | ||
232 | struct ecryptfs_daemon *daemon; | ||
233 | int rc; | ||
234 | |||
235 | mutex_lock(&ecryptfs_daemon_hash_mux); | ||
236 | rc = ecryptfs_find_daemon_by_euid(&daemon, euid, user_ns); | ||
237 | if (rc || !daemon) { | ||
238 | rc = -EINVAL; | ||
239 | printk(KERN_ERR "Received request from user [%d] to " | ||
240 | "unregister unrecognized daemon [0x%p]\n", euid, pid); | ||
241 | goto out_unlock; | ||
242 | } | ||
243 | rc = ecryptfs_exorcise_daemon(daemon); | ||
244 | out_unlock: | ||
245 | mutex_unlock(&ecryptfs_daemon_hash_mux); | ||
246 | return rc; | ||
247 | } | ||
248 | |||
249 | /** | ||
250 | * ecryptfs_process_reponse | 202 | * ecryptfs_process_reponse |
251 | * @msg: The ecryptfs message received; the caller should sanity check | 203 | * @msg: The ecryptfs message received; the caller should sanity check |
252 | * msg->data_len and free the memory | 204 | * msg->data_len and free the memory |
253 | * @pid: The process ID of the userspace application that sent the | ||
254 | * message | ||
255 | * @seq: The sequence number of the message; must match the sequence | 205 | * @seq: The sequence number of the message; must match the sequence |
256 | * number for the existing message context waiting for this | 206 | * number for the existing message context waiting for this |
257 | * response | 207 | * response |
@@ -270,16 +220,11 @@ out_unlock: | |||
270 | * | 220 | * |
271 | * Returns zero on success; non-zero otherwise | 221 | * Returns zero on success; non-zero otherwise |
272 | */ | 222 | */ |
273 | int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t euid, | 223 | int ecryptfs_process_response(struct ecryptfs_daemon *daemon, |
274 | struct user_namespace *user_ns, struct pid *pid, | 224 | struct ecryptfs_message *msg, u32 seq) |
275 | u32 seq) | ||
276 | { | 225 | { |
277 | struct ecryptfs_daemon *uninitialized_var(daemon); | ||
278 | struct ecryptfs_msg_ctx *msg_ctx; | 226 | struct ecryptfs_msg_ctx *msg_ctx; |
279 | size_t msg_size; | 227 | size_t msg_size; |
280 | struct nsproxy *nsproxy; | ||
281 | struct user_namespace *tsk_user_ns; | ||
282 | uid_t ctx_euid; | ||
283 | int rc; | 228 | int rc; |
284 | 229 | ||
285 | if (msg->index >= ecryptfs_message_buf_len) { | 230 | if (msg->index >= ecryptfs_message_buf_len) { |
@@ -292,51 +237,6 @@ int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t euid, | |||
292 | } | 237 | } |
293 | msg_ctx = &ecryptfs_msg_ctx_arr[msg->index]; | 238 | msg_ctx = &ecryptfs_msg_ctx_arr[msg->index]; |
294 | mutex_lock(&msg_ctx->mux); | 239 | mutex_lock(&msg_ctx->mux); |
295 | mutex_lock(&ecryptfs_daemon_hash_mux); | ||
296 | rcu_read_lock(); | ||
297 | nsproxy = task_nsproxy(msg_ctx->task); | ||
298 | if (nsproxy == NULL) { | ||
299 | rc = -EBADMSG; | ||
300 | printk(KERN_ERR "%s: Receiving process is a zombie. Dropping " | ||
301 | "message.\n", __func__); | ||
302 | rcu_read_unlock(); | ||
303 | mutex_unlock(&ecryptfs_daemon_hash_mux); | ||
304 | goto wake_up; | ||
305 | } | ||
306 | tsk_user_ns = __task_cred(msg_ctx->task)->user_ns; | ||
307 | ctx_euid = task_euid(msg_ctx->task); | ||
308 | rc = ecryptfs_find_daemon_by_euid(&daemon, ctx_euid, tsk_user_ns); | ||
309 | rcu_read_unlock(); | ||
310 | mutex_unlock(&ecryptfs_daemon_hash_mux); | ||
311 | if (rc) { | ||
312 | rc = -EBADMSG; | ||
313 | printk(KERN_WARNING "%s: User [%d] received a " | ||
314 | "message response from process [0x%p] but does " | ||
315 | "not have a registered daemon\n", __func__, | ||
316 | ctx_euid, pid); | ||
317 | goto wake_up; | ||
318 | } | ||
319 | if (ctx_euid != euid) { | ||
320 | rc = -EBADMSG; | ||
321 | printk(KERN_WARNING "%s: Received message from user " | ||
322 | "[%d]; expected message from user [%d]\n", __func__, | ||
323 | euid, ctx_euid); | ||
324 | goto unlock; | ||
325 | } | ||
326 | if (tsk_user_ns != user_ns) { | ||
327 | rc = -EBADMSG; | ||
328 | printk(KERN_WARNING "%s: Received message from user_ns " | ||
329 | "[0x%p]; expected message from user_ns [0x%p]\n", | ||
330 | __func__, user_ns, tsk_user_ns); | ||
331 | goto unlock; | ||
332 | } | ||
333 | if (daemon->pid != pid) { | ||
334 | rc = -EBADMSG; | ||
335 | printk(KERN_ERR "%s: User [%d] sent a message response " | ||
336 | "from an unrecognized process [0x%p]\n", | ||
337 | __func__, ctx_euid, pid); | ||
338 | goto unlock; | ||
339 | } | ||
340 | if (msg_ctx->state != ECRYPTFS_MSG_CTX_STATE_PENDING) { | 240 | if (msg_ctx->state != ECRYPTFS_MSG_CTX_STATE_PENDING) { |
341 | rc = -EINVAL; | 241 | rc = -EINVAL; |
342 | printk(KERN_WARNING "%s: Desired context element is not " | 242 | printk(KERN_WARNING "%s: Desired context element is not " |
@@ -359,9 +259,8 @@ int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t euid, | |||
359 | } | 259 | } |
360 | memcpy(msg_ctx->msg, msg, msg_size); | 260 | memcpy(msg_ctx->msg, msg, msg_size); |
361 | msg_ctx->state = ECRYPTFS_MSG_CTX_STATE_DONE; | 261 | msg_ctx->state = ECRYPTFS_MSG_CTX_STATE_DONE; |
362 | rc = 0; | ||
363 | wake_up: | ||
364 | wake_up_process(msg_ctx->task); | 262 | wake_up_process(msg_ctx->task); |
263 | rc = 0; | ||
365 | unlock: | 264 | unlock: |
366 | mutex_unlock(&msg_ctx->mux); | 265 | mutex_unlock(&msg_ctx->mux); |
367 | out: | 266 | out: |
@@ -383,14 +282,11 @@ ecryptfs_send_message_locked(char *data, int data_len, u8 msg_type, | |||
383 | struct ecryptfs_msg_ctx **msg_ctx) | 282 | struct ecryptfs_msg_ctx **msg_ctx) |
384 | { | 283 | { |
385 | struct ecryptfs_daemon *daemon; | 284 | struct ecryptfs_daemon *daemon; |
386 | uid_t euid = current_euid(); | ||
387 | int rc; | 285 | int rc; |
388 | 286 | ||
389 | rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns()); | 287 | rc = ecryptfs_find_daemon_by_euid(&daemon); |
390 | if (rc || !daemon) { | 288 | if (rc || !daemon) { |
391 | rc = -ENOTCONN; | 289 | rc = -ENOTCONN; |
392 | printk(KERN_ERR "%s: User [%d] does not have a daemon " | ||
393 | "registered\n", __func__, euid); | ||
394 | goto out; | 290 | goto out; |
395 | } | 291 | } |
396 | mutex_lock(&ecryptfs_msg_ctx_lists_mux); | 292 | mutex_lock(&ecryptfs_msg_ctx_lists_mux); |
diff --git a/fs/ecryptfs/miscdev.c b/fs/ecryptfs/miscdev.c index c0038f6566d..412e6eda25f 100644 --- a/fs/ecryptfs/miscdev.c +++ b/fs/ecryptfs/miscdev.c | |||
@@ -33,7 +33,7 @@ static atomic_t ecryptfs_num_miscdev_opens; | |||
33 | 33 | ||
34 | /** | 34 | /** |
35 | * ecryptfs_miscdev_poll | 35 | * ecryptfs_miscdev_poll |
36 | * @file: dev file (ignored) | 36 | * @file: dev file |
37 | * @pt: dev poll table (ignored) | 37 | * @pt: dev poll table (ignored) |
38 | * | 38 | * |
39 | * Returns the poll mask | 39 | * Returns the poll mask |
@@ -41,20 +41,10 @@ static atomic_t ecryptfs_num_miscdev_opens; | |||
41 | static unsigned int | 41 | static unsigned int |
42 | ecryptfs_miscdev_poll(struct file *file, poll_table *pt) | 42 | ecryptfs_miscdev_poll(struct file *file, poll_table *pt) |
43 | { | 43 | { |
44 | struct ecryptfs_daemon *daemon; | 44 | struct ecryptfs_daemon *daemon = file->private_data; |
45 | unsigned int mask = 0; | 45 | unsigned int mask = 0; |
46 | uid_t euid = current_euid(); | ||
47 | int rc; | ||
48 | 46 | ||
49 | mutex_lock(&ecryptfs_daemon_hash_mux); | ||
50 | /* TODO: Just use file->private_data? */ | ||
51 | rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns()); | ||
52 | if (rc || !daemon) { | ||
53 | mutex_unlock(&ecryptfs_daemon_hash_mux); | ||
54 | return -EINVAL; | ||
55 | } | ||
56 | mutex_lock(&daemon->mux); | 47 | mutex_lock(&daemon->mux); |
57 | mutex_unlock(&ecryptfs_daemon_hash_mux); | ||
58 | if (daemon->flags & ECRYPTFS_DAEMON_ZOMBIE) { | 48 | if (daemon->flags & ECRYPTFS_DAEMON_ZOMBIE) { |
59 | printk(KERN_WARNING "%s: Attempt to poll on zombified " | 49 | printk(KERN_WARNING "%s: Attempt to poll on zombified " |
60 | "daemon\n", __func__); | 50 | "daemon\n", __func__); |
@@ -79,7 +69,7 @@ out_unlock_daemon: | |||
79 | /** | 69 | /** |
80 | * ecryptfs_miscdev_open | 70 | * ecryptfs_miscdev_open |
81 | * @inode: inode of miscdev handle (ignored) | 71 | * @inode: inode of miscdev handle (ignored) |
82 | * @file: file for miscdev handle (ignored) | 72 | * @file: file for miscdev handle |
83 | * | 73 | * |
84 | * Returns zero on success; non-zero otherwise | 74 | * Returns zero on success; non-zero otherwise |
85 | */ | 75 | */ |
@@ -87,7 +77,6 @@ static int | |||
87 | ecryptfs_miscdev_open(struct inode *inode, struct file *file) | 77 | ecryptfs_miscdev_open(struct inode *inode, struct file *file) |
88 | { | 78 | { |
89 | struct ecryptfs_daemon *daemon = NULL; | 79 | struct ecryptfs_daemon *daemon = NULL; |
90 | uid_t euid = current_euid(); | ||
91 | int rc; | 80 | int rc; |
92 | 81 | ||
93 | mutex_lock(&ecryptfs_daemon_hash_mux); | 82 | mutex_lock(&ecryptfs_daemon_hash_mux); |
@@ -98,30 +87,20 @@ ecryptfs_miscdev_open(struct inode *inode, struct file *file) | |||
98 | "count; rc = [%d]\n", __func__, rc); | 87 | "count; rc = [%d]\n", __func__, rc); |
99 | goto out_unlock_daemon_list; | 88 | goto out_unlock_daemon_list; |
100 | } | 89 | } |
101 | rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns()); | 90 | rc = ecryptfs_find_daemon_by_euid(&daemon); |
102 | if (rc || !daemon) { | 91 | if (!rc) { |
103 | rc = ecryptfs_spawn_daemon(&daemon, euid, current_user_ns(), | ||
104 | task_pid(current)); | ||
105 | if (rc) { | ||
106 | printk(KERN_ERR "%s: Error attempting to spawn daemon; " | ||
107 | "rc = [%d]\n", __func__, rc); | ||
108 | goto out_module_put_unlock_daemon_list; | ||
109 | } | ||
110 | } | ||
111 | mutex_lock(&daemon->mux); | ||
112 | if (daemon->pid != task_pid(current)) { | ||
113 | rc = -EINVAL; | 92 | rc = -EINVAL; |
114 | printk(KERN_ERR "%s: pid [0x%p] has registered with euid [%d], " | 93 | goto out_unlock_daemon_list; |
115 | "but pid [0x%p] has attempted to open the handle " | 94 | } |
116 | "instead\n", __func__, daemon->pid, daemon->euid, | 95 | rc = ecryptfs_spawn_daemon(&daemon, file); |
117 | task_pid(current)); | 96 | if (rc) { |
118 | goto out_unlock_daemon; | 97 | printk(KERN_ERR "%s: Error attempting to spawn daemon; " |
98 | "rc = [%d]\n", __func__, rc); | ||
99 | goto out_module_put_unlock_daemon_list; | ||
119 | } | 100 | } |
101 | mutex_lock(&daemon->mux); | ||
120 | if (daemon->flags & ECRYPTFS_DAEMON_MISCDEV_OPEN) { | 102 | if (daemon->flags & ECRYPTFS_DAEMON_MISCDEV_OPEN) { |
121 | rc = -EBUSY; | 103 | rc = -EBUSY; |
122 | printk(KERN_ERR "%s: Miscellaneous device handle may only be " | ||
123 | "opened once per daemon; pid [0x%p] already has this " | ||
124 | "handle open\n", __func__, daemon->pid); | ||
125 | goto out_unlock_daemon; | 104 | goto out_unlock_daemon; |
126 | } | 105 | } |
127 | daemon->flags |= ECRYPTFS_DAEMON_MISCDEV_OPEN; | 106 | daemon->flags |= ECRYPTFS_DAEMON_MISCDEV_OPEN; |
@@ -140,7 +119,7 @@ out_unlock_daemon_list: | |||
140 | /** | 119 | /** |
141 | * ecryptfs_miscdev_release | 120 | * ecryptfs_miscdev_release |
142 | * @inode: inode of fs/ecryptfs/euid handle (ignored) | 121 | * @inode: inode of fs/ecryptfs/euid handle (ignored) |
143 | * @file: file for fs/ecryptfs/euid handle (ignored) | 122 | * @file: file for fs/ecryptfs/euid handle |
144 | * | 123 | * |
145 | * This keeps the daemon registered until the daemon sends another | 124 | * This keeps the daemon registered until the daemon sends another |
146 | * ioctl to fs/ecryptfs/ctl or until the kernel module unregisters. | 125 | * ioctl to fs/ecryptfs/ctl or until the kernel module unregisters. |
@@ -150,20 +129,18 @@ out_unlock_daemon_list: | |||
150 | static int | 129 | static int |
151 | ecryptfs_miscdev_release(struct inode *inode, struct file *file) | 130 | ecryptfs_miscdev_release(struct inode *inode, struct file *file) |
152 | { | 131 | { |
153 | struct ecryptfs_daemon *daemon = NULL; | 132 | struct ecryptfs_daemon *daemon = file->private_data; |
154 | uid_t euid = current_euid(); | ||
155 | int rc; | 133 | int rc; |
156 | 134 | ||
157 | mutex_lock(&ecryptfs_daemon_hash_mux); | ||
158 | rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns()); | ||
159 | if (rc || !daemon) | ||
160 | daemon = file->private_data; | ||
161 | mutex_lock(&daemon->mux); | 135 | mutex_lock(&daemon->mux); |
162 | BUG_ON(!(daemon->flags & ECRYPTFS_DAEMON_MISCDEV_OPEN)); | 136 | BUG_ON(!(daemon->flags & ECRYPTFS_DAEMON_MISCDEV_OPEN)); |
163 | daemon->flags &= ~ECRYPTFS_DAEMON_MISCDEV_OPEN; | 137 | daemon->flags &= ~ECRYPTFS_DAEMON_MISCDEV_OPEN; |
164 | atomic_dec(&ecryptfs_num_miscdev_opens); | 138 | atomic_dec(&ecryptfs_num_miscdev_opens); |
165 | mutex_unlock(&daemon->mux); | 139 | mutex_unlock(&daemon->mux); |
140 | |||
141 | mutex_lock(&ecryptfs_daemon_hash_mux); | ||
166 | rc = ecryptfs_exorcise_daemon(daemon); | 142 | rc = ecryptfs_exorcise_daemon(daemon); |
143 | mutex_unlock(&ecryptfs_daemon_hash_mux); | ||
167 | if (rc) { | 144 | if (rc) { |
168 | printk(KERN_CRIT "%s: Fatal error whilst attempting to " | 145 | printk(KERN_CRIT "%s: Fatal error whilst attempting to " |
169 | "shut down daemon; rc = [%d]. Please report this " | 146 | "shut down daemon; rc = [%d]. Please report this " |
@@ -171,7 +148,6 @@ ecryptfs_miscdev_release(struct inode *inode, struct file *file) | |||
171 | BUG(); | 148 | BUG(); |
172 | } | 149 | } |
173 | module_put(THIS_MODULE); | 150 | module_put(THIS_MODULE); |
174 | mutex_unlock(&ecryptfs_daemon_hash_mux); | ||
175 | return rc; | 151 | return rc; |
176 | } | 152 | } |
177 | 153 | ||
@@ -248,7 +224,7 @@ int ecryptfs_send_miscdev(char *data, size_t data_size, | |||
248 | 224 | ||
249 | /** | 225 | /** |
250 | * ecryptfs_miscdev_read - format and send message from queue | 226 | * ecryptfs_miscdev_read - format and send message from queue |
251 | * @file: fs/ecryptfs/euid miscdevfs handle (ignored) | 227 | * @file: miscdevfs handle |
252 | * @buf: User buffer into which to copy the next message on the daemon queue | 228 | * @buf: User buffer into which to copy the next message on the daemon queue |
253 | * @count: Amount of space available in @buf | 229 | * @count: Amount of space available in @buf |
254 | * @ppos: Offset in file (ignored) | 230 | * @ppos: Offset in file (ignored) |
@@ -262,43 +238,27 @@ static ssize_t | |||
262 | ecryptfs_miscdev_read(struct file *file, char __user *buf, size_t count, | 238 | ecryptfs_miscdev_read(struct file *file, char __user *buf, size_t count, |
263 | loff_t *ppos) | 239 | loff_t *ppos) |
264 | { | 240 | { |
265 | struct ecryptfs_daemon *daemon; | 241 | struct ecryptfs_daemon *daemon = file->private_data; |
266 | struct ecryptfs_msg_ctx *msg_ctx; | 242 | struct ecryptfs_msg_ctx *msg_ctx; |
267 | size_t packet_length_size; | 243 | size_t packet_length_size; |
268 | char packet_length[ECRYPTFS_MAX_PKT_LEN_SIZE]; | 244 | char packet_length[ECRYPTFS_MAX_PKT_LEN_SIZE]; |
269 | size_t i; | 245 | size_t i; |
270 | size_t total_length; | 246 | size_t total_length; |
271 | uid_t euid = current_euid(); | ||
272 | int rc; | 247 | int rc; |
273 | 248 | ||
274 | mutex_lock(&ecryptfs_daemon_hash_mux); | ||
275 | /* TODO: Just use file->private_data? */ | ||
276 | rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns()); | ||
277 | if (rc || !daemon) { | ||
278 | mutex_unlock(&ecryptfs_daemon_hash_mux); | ||
279 | return -EINVAL; | ||
280 | } | ||
281 | mutex_lock(&daemon->mux); | 249 | mutex_lock(&daemon->mux); |
282 | if (task_pid(current) != daemon->pid) { | ||
283 | mutex_unlock(&daemon->mux); | ||
284 | mutex_unlock(&ecryptfs_daemon_hash_mux); | ||
285 | return -EPERM; | ||
286 | } | ||
287 | if (daemon->flags & ECRYPTFS_DAEMON_ZOMBIE) { | 250 | if (daemon->flags & ECRYPTFS_DAEMON_ZOMBIE) { |
288 | rc = 0; | 251 | rc = 0; |
289 | mutex_unlock(&ecryptfs_daemon_hash_mux); | ||
290 | printk(KERN_WARNING "%s: Attempt to read from zombified " | 252 | printk(KERN_WARNING "%s: Attempt to read from zombified " |
291 | "daemon\n", __func__); | 253 | "daemon\n", __func__); |
292 | goto out_unlock_daemon; | 254 | goto out_unlock_daemon; |
293 | } | 255 | } |
294 | if (daemon->flags & ECRYPTFS_DAEMON_IN_READ) { | 256 | if (daemon->flags & ECRYPTFS_DAEMON_IN_READ) { |
295 | rc = 0; | 257 | rc = 0; |
296 | mutex_unlock(&ecryptfs_daemon_hash_mux); | ||
297 | goto out_unlock_daemon; | 258 | goto out_unlock_daemon; |
298 | } | 259 | } |
299 | /* This daemon will not go away so long as this flag is set */ | 260 | /* This daemon will not go away so long as this flag is set */ |
300 | daemon->flags |= ECRYPTFS_DAEMON_IN_READ; | 261 | daemon->flags |= ECRYPTFS_DAEMON_IN_READ; |
301 | mutex_unlock(&ecryptfs_daemon_hash_mux); | ||
302 | check_list: | 262 | check_list: |
303 | if (list_empty(&daemon->msg_ctx_out_queue)) { | 263 | if (list_empty(&daemon->msg_ctx_out_queue)) { |
304 | mutex_unlock(&daemon->mux); | 264 | mutex_unlock(&daemon->mux); |
@@ -382,16 +342,12 @@ out_unlock_daemon: | |||
382 | * ecryptfs_miscdev_response - miscdevess response to message previously sent to daemon | 342 | * ecryptfs_miscdev_response - miscdevess response to message previously sent to daemon |
383 | * @data: Bytes comprising struct ecryptfs_message | 343 | * @data: Bytes comprising struct ecryptfs_message |
384 | * @data_size: sizeof(struct ecryptfs_message) + data len | 344 | * @data_size: sizeof(struct ecryptfs_message) + data len |
385 | * @euid: Effective user id of miscdevess sending the miscdev response | ||
386 | * @user_ns: The namespace in which @euid applies | ||
387 | * @pid: Miscdevess id of miscdevess sending the miscdev response | ||
388 | * @seq: Sequence number for miscdev response packet | 345 | * @seq: Sequence number for miscdev response packet |
389 | * | 346 | * |
390 | * Returns zero on success; non-zero otherwise | 347 | * Returns zero on success; non-zero otherwise |
391 | */ | 348 | */ |
392 | static int ecryptfs_miscdev_response(char *data, size_t data_size, | 349 | static int ecryptfs_miscdev_response(struct ecryptfs_daemon *daemon, char *data, |
393 | uid_t euid, struct user_namespace *user_ns, | 350 | size_t data_size, u32 seq) |
394 | struct pid *pid, u32 seq) | ||
395 | { | 351 | { |
396 | struct ecryptfs_message *msg = (struct ecryptfs_message *)data; | 352 | struct ecryptfs_message *msg = (struct ecryptfs_message *)data; |
397 | int rc; | 353 | int rc; |
@@ -403,7 +359,7 @@ static int ecryptfs_miscdev_response(char *data, size_t data_size, | |||
403 | rc = -EINVAL; | 359 | rc = -EINVAL; |
404 | goto out; | 360 | goto out; |
405 | } | 361 | } |
406 | rc = ecryptfs_process_response(msg, euid, user_ns, pid, seq); | 362 | rc = ecryptfs_process_response(daemon, msg, seq); |
407 | if (rc) | 363 | if (rc) |
408 | printk(KERN_ERR | 364 | printk(KERN_ERR |
409 | "Error processing response message; rc = [%d]\n", rc); | 365 | "Error processing response message; rc = [%d]\n", rc); |
@@ -413,7 +369,7 @@ out: | |||
413 | 369 | ||
414 | /** | 370 | /** |
415 | * ecryptfs_miscdev_write - handle write to daemon miscdev handle | 371 | * ecryptfs_miscdev_write - handle write to daemon miscdev handle |
416 | * @file: File for misc dev handle (ignored) | 372 | * @file: File for misc dev handle |
417 | * @buf: Buffer containing user data | 373 | * @buf: Buffer containing user data |
418 | * @count: Amount of data in @buf | 374 | * @count: Amount of data in @buf |
419 | * @ppos: Pointer to offset in file (ignored) | 375 | * @ppos: Pointer to offset in file (ignored) |
@@ -428,7 +384,6 @@ ecryptfs_miscdev_write(struct file *file, const char __user *buf, | |||
428 | u32 seq; | 384 | u32 seq; |
429 | size_t packet_size, packet_size_length; | 385 | size_t packet_size, packet_size_length; |
430 | char *data; | 386 | char *data; |
431 | uid_t euid = current_euid(); | ||
432 | unsigned char packet_size_peek[ECRYPTFS_MAX_PKT_LEN_SIZE]; | 387 | unsigned char packet_size_peek[ECRYPTFS_MAX_PKT_LEN_SIZE]; |
433 | ssize_t rc; | 388 | ssize_t rc; |
434 | 389 | ||
@@ -488,10 +443,9 @@ memdup: | |||
488 | } | 443 | } |
489 | memcpy(&counter_nbo, &data[PKT_CTR_OFFSET], PKT_CTR_SIZE); | 444 | memcpy(&counter_nbo, &data[PKT_CTR_OFFSET], PKT_CTR_SIZE); |
490 | seq = be32_to_cpu(counter_nbo); | 445 | seq = be32_to_cpu(counter_nbo); |
491 | rc = ecryptfs_miscdev_response( | 446 | rc = ecryptfs_miscdev_response(file->private_data, |
492 | &data[PKT_LEN_OFFSET + packet_size_length], | 447 | &data[PKT_LEN_OFFSET + packet_size_length], |
493 | packet_size, euid, current_user_ns(), | 448 | packet_size, seq); |
494 | task_pid(current), seq); | ||
495 | if (rc) { | 449 | if (rc) { |
496 | printk(KERN_WARNING "%s: Failed to deliver miscdev " | 450 | printk(KERN_WARNING "%s: Failed to deliver miscdev " |
497 | "response to requesting operation; rc = [%zd]\n", | 451 | "response to requesting operation; rc = [%zd]\n", |
diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c index a46b3a8fee1..bd1d57f98f7 100644 --- a/fs/ecryptfs/mmap.c +++ b/fs/ecryptfs/mmap.c | |||
@@ -66,18 +66,6 @@ static int ecryptfs_writepage(struct page *page, struct writeback_control *wbc) | |||
66 | { | 66 | { |
67 | int rc; | 67 | int rc; |
68 | 68 | ||
69 | /* | ||
70 | * Refuse to write the page out if we are called from reclaim context | ||
71 | * since our writepage() path may potentially allocate memory when | ||
72 | * calling into the lower fs vfs_write() which may in turn invoke | ||
73 | * us again. | ||
74 | */ | ||
75 | if (current->flags & PF_MEMALLOC) { | ||
76 | redirty_page_for_writepage(wbc, page); | ||
77 | rc = 0; | ||
78 | goto out; | ||
79 | } | ||
80 | |||
81 | rc = ecryptfs_encrypt_page(page); | 69 | rc = ecryptfs_encrypt_page(page); |
82 | if (rc) { | 70 | if (rc) { |
83 | ecryptfs_printk(KERN_WARNING, "Error encrypting " | 71 | ecryptfs_printk(KERN_WARNING, "Error encrypting " |
@@ -498,7 +486,6 @@ static int ecryptfs_write_end(struct file *file, | |||
498 | struct ecryptfs_crypt_stat *crypt_stat = | 486 | struct ecryptfs_crypt_stat *crypt_stat = |
499 | &ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat; | 487 | &ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat; |
500 | int rc; | 488 | int rc; |
501 | int need_unlock_page = 1; | ||
502 | 489 | ||
503 | ecryptfs_printk(KERN_DEBUG, "Calling fill_zeros_to_end_of_page" | 490 | ecryptfs_printk(KERN_DEBUG, "Calling fill_zeros_to_end_of_page" |
504 | "(page w/ index = [0x%.16lx], to = [%d])\n", index, to); | 491 | "(page w/ index = [0x%.16lx], to = [%d])\n", index, to); |
@@ -519,26 +506,26 @@ static int ecryptfs_write_end(struct file *file, | |||
519 | "zeros in page with index = [0x%.16lx]\n", index); | 506 | "zeros in page with index = [0x%.16lx]\n", index); |
520 | goto out; | 507 | goto out; |
521 | } | 508 | } |
522 | set_page_dirty(page); | 509 | rc = ecryptfs_encrypt_page(page); |
523 | unlock_page(page); | 510 | if (rc) { |
524 | need_unlock_page = 0; | 511 | ecryptfs_printk(KERN_WARNING, "Error encrypting page (upper " |
512 | "index [0x%.16lx])\n", index); | ||
513 | goto out; | ||
514 | } | ||
525 | if (pos + copied > i_size_read(ecryptfs_inode)) { | 515 | if (pos + copied > i_size_read(ecryptfs_inode)) { |
526 | i_size_write(ecryptfs_inode, pos + copied); | 516 | i_size_write(ecryptfs_inode, pos + copied); |
527 | ecryptfs_printk(KERN_DEBUG, "Expanded file size to " | 517 | ecryptfs_printk(KERN_DEBUG, "Expanded file size to " |
528 | "[0x%.16llx]\n", | 518 | "[0x%.16llx]\n", |
529 | (unsigned long long)i_size_read(ecryptfs_inode)); | 519 | (unsigned long long)i_size_read(ecryptfs_inode)); |
530 | balance_dirty_pages_ratelimited(mapping); | ||
531 | rc = ecryptfs_write_inode_size_to_metadata(ecryptfs_inode); | ||
532 | if (rc) { | ||
533 | printk(KERN_ERR "Error writing inode size to metadata; " | ||
534 | "rc = [%d]\n", rc); | ||
535 | goto out; | ||
536 | } | ||
537 | } | 520 | } |
538 | rc = copied; | 521 | rc = ecryptfs_write_inode_size_to_metadata(ecryptfs_inode); |
522 | if (rc) | ||
523 | printk(KERN_ERR "Error writing inode size to metadata; " | ||
524 | "rc = [%d]\n", rc); | ||
525 | else | ||
526 | rc = copied; | ||
539 | out: | 527 | out: |
540 | if (need_unlock_page) | 528 | unlock_page(page); |
541 | unlock_page(page); | ||
542 | page_cache_release(page); | 529 | page_cache_release(page); |
543 | return rc; | 530 | return rc; |
544 | } | 531 | } |
diff --git a/fs/eventpoll.c b/fs/eventpoll.c index 1c8b5567080..eedec84c180 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c | |||
@@ -1654,8 +1654,8 @@ SYSCALL_DEFINE1(epoll_create1, int, flags) | |||
1654 | error = PTR_ERR(file); | 1654 | error = PTR_ERR(file); |
1655 | goto out_free_fd; | 1655 | goto out_free_fd; |
1656 | } | 1656 | } |
1657 | fd_install(fd, file); | ||
1658 | ep->file = file; | 1657 | ep->file = file; |
1658 | fd_install(fd, file); | ||
1659 | return fd; | 1659 | return fd; |
1660 | 1660 | ||
1661 | out_free_fd: | 1661 | out_free_fd: |
diff --git a/fs/exofs/inode.c b/fs/exofs/inode.c index 5badb0c039d..1562c27a2fa 100644 --- a/fs/exofs/inode.c +++ b/fs/exofs/inode.c | |||
@@ -37,15 +37,12 @@ | |||
37 | 37 | ||
38 | #define EXOFS_DBGMSG2(M...) do {} while (0) | 38 | #define EXOFS_DBGMSG2(M...) do {} while (0) |
39 | 39 | ||
40 | enum {MAX_PAGES_KMALLOC = PAGE_SIZE / sizeof(struct page *), }; | ||
41 | |||
42 | unsigned exofs_max_io_pages(struct ore_layout *layout, | 40 | unsigned exofs_max_io_pages(struct ore_layout *layout, |
43 | unsigned expected_pages) | 41 | unsigned expected_pages) |
44 | { | 42 | { |
45 | unsigned pages = min_t(unsigned, expected_pages, MAX_PAGES_KMALLOC); | 43 | unsigned pages = min_t(unsigned, expected_pages, |
44 | layout->max_io_length / PAGE_SIZE); | ||
46 | 45 | ||
47 | /* TODO: easily support bio chaining */ | ||
48 | pages = min_t(unsigned, pages, layout->max_io_length / PAGE_SIZE); | ||
49 | return pages; | 46 | return pages; |
50 | } | 47 | } |
51 | 48 | ||
@@ -101,7 +98,8 @@ static void _pcol_reset(struct page_collect *pcol) | |||
101 | * it might not end here. don't be left with nothing | 98 | * it might not end here. don't be left with nothing |
102 | */ | 99 | */ |
103 | if (!pcol->expected_pages) | 100 | if (!pcol->expected_pages) |
104 | pcol->expected_pages = MAX_PAGES_KMALLOC; | 101 | pcol->expected_pages = |
102 | exofs_max_io_pages(&pcol->sbi->layout, ~0); | ||
105 | } | 103 | } |
106 | 104 | ||
107 | static int pcol_try_alloc(struct page_collect *pcol) | 105 | static int pcol_try_alloc(struct page_collect *pcol) |
@@ -389,6 +387,8 @@ static int readpage_strip(void *data, struct page *page) | |||
389 | size_t len; | 387 | size_t len; |
390 | int ret; | 388 | int ret; |
391 | 389 | ||
390 | BUG_ON(!PageLocked(page)); | ||
391 | |||
392 | /* FIXME: Just for debugging, will be removed */ | 392 | /* FIXME: Just for debugging, will be removed */ |
393 | if (PageUptodate(page)) | 393 | if (PageUptodate(page)) |
394 | EXOFS_ERR("PageUptodate(0x%lx, 0x%lx)\n", pcol->inode->i_ino, | 394 | EXOFS_ERR("PageUptodate(0x%lx, 0x%lx)\n", pcol->inode->i_ino, |
@@ -572,8 +572,16 @@ static struct page *__r4w_get_page(void *priv, u64 offset, bool *uptodate) | |||
572 | 572 | ||
573 | if (!pcol->that_locked_page || | 573 | if (!pcol->that_locked_page || |
574 | (pcol->that_locked_page->index != index)) { | 574 | (pcol->that_locked_page->index != index)) { |
575 | struct page *page = find_get_page(pcol->inode->i_mapping, index); | 575 | struct page *page; |
576 | loff_t i_size = i_size_read(pcol->inode); | ||
577 | |||
578 | if (offset >= i_size) { | ||
579 | *uptodate = true; | ||
580 | EXOFS_DBGMSG("offset >= i_size index=0x%lx\n", index); | ||
581 | return ZERO_PAGE(0); | ||
582 | } | ||
576 | 583 | ||
584 | page = find_get_page(pcol->inode->i_mapping, index); | ||
577 | if (!page) { | 585 | if (!page) { |
578 | page = find_or_create_page(pcol->inode->i_mapping, | 586 | page = find_or_create_page(pcol->inode->i_mapping, |
579 | index, GFP_NOFS); | 587 | index, GFP_NOFS); |
@@ -602,12 +610,13 @@ static void __r4w_put_page(void *priv, struct page *page) | |||
602 | { | 610 | { |
603 | struct page_collect *pcol = priv; | 611 | struct page_collect *pcol = priv; |
604 | 612 | ||
605 | if (pcol->that_locked_page != page) { | 613 | if ((pcol->that_locked_page != page) && (ZERO_PAGE(0) != page)) { |
606 | EXOFS_DBGMSG("index=0x%lx\n", page->index); | 614 | EXOFS_DBGMSG("index=0x%lx\n", page->index); |
607 | page_cache_release(page); | 615 | page_cache_release(page); |
608 | return; | 616 | return; |
609 | } | 617 | } |
610 | EXOFS_DBGMSG("that_locked_page index=0x%lx\n", page->index); | 618 | EXOFS_DBGMSG("that_locked_page index=0x%lx\n", |
619 | ZERO_PAGE(0) == page ? -1 : page->index); | ||
611 | } | 620 | } |
612 | 621 | ||
613 | static const struct _ore_r4w_op _r4w_op = { | 622 | static const struct _ore_r4w_op _r4w_op = { |
diff --git a/fs/exofs/ore.c b/fs/exofs/ore.c index 24a49d47e93..1585db1aa36 100644 --- a/fs/exofs/ore.c +++ b/fs/exofs/ore.c | |||
@@ -837,11 +837,11 @@ static int _write_mirror(struct ore_io_state *ios, int cur_comp) | |||
837 | bio->bi_rw |= REQ_WRITE; | 837 | bio->bi_rw |= REQ_WRITE; |
838 | } | 838 | } |
839 | 839 | ||
840 | osd_req_write(or, _ios_obj(ios, dev), per_dev->offset, | 840 | osd_req_write(or, _ios_obj(ios, cur_comp), |
841 | bio, per_dev->length); | 841 | per_dev->offset, bio, per_dev->length); |
842 | ORE_DBGMSG("write(0x%llx) offset=0x%llx " | 842 | ORE_DBGMSG("write(0x%llx) offset=0x%llx " |
843 | "length=0x%llx dev=%d\n", | 843 | "length=0x%llx dev=%d\n", |
844 | _LLU(_ios_obj(ios, dev)->id), | 844 | _LLU(_ios_obj(ios, cur_comp)->id), |
845 | _LLU(per_dev->offset), | 845 | _LLU(per_dev->offset), |
846 | _LLU(per_dev->length), dev); | 846 | _LLU(per_dev->length), dev); |
847 | } else if (ios->kern_buff) { | 847 | } else if (ios->kern_buff) { |
@@ -853,20 +853,20 @@ static int _write_mirror(struct ore_io_state *ios, int cur_comp) | |||
853 | (ios->si.unit_off + ios->length > | 853 | (ios->si.unit_off + ios->length > |
854 | ios->layout->stripe_unit)); | 854 | ios->layout->stripe_unit)); |
855 | 855 | ||
856 | ret = osd_req_write_kern(or, _ios_obj(ios, per_dev->dev), | 856 | ret = osd_req_write_kern(or, _ios_obj(ios, cur_comp), |
857 | per_dev->offset, | 857 | per_dev->offset, |
858 | ios->kern_buff, ios->length); | 858 | ios->kern_buff, ios->length); |
859 | if (unlikely(ret)) | 859 | if (unlikely(ret)) |
860 | goto out; | 860 | goto out; |
861 | ORE_DBGMSG2("write_kern(0x%llx) offset=0x%llx " | 861 | ORE_DBGMSG2("write_kern(0x%llx) offset=0x%llx " |
862 | "length=0x%llx dev=%d\n", | 862 | "length=0x%llx dev=%d\n", |
863 | _LLU(_ios_obj(ios, dev)->id), | 863 | _LLU(_ios_obj(ios, cur_comp)->id), |
864 | _LLU(per_dev->offset), | 864 | _LLU(per_dev->offset), |
865 | _LLU(ios->length), per_dev->dev); | 865 | _LLU(ios->length), per_dev->dev); |
866 | } else { | 866 | } else { |
867 | osd_req_set_attributes(or, _ios_obj(ios, dev)); | 867 | osd_req_set_attributes(or, _ios_obj(ios, cur_comp)); |
868 | ORE_DBGMSG2("obj(0x%llx) set_attributes=%d dev=%d\n", | 868 | ORE_DBGMSG2("obj(0x%llx) set_attributes=%d dev=%d\n", |
869 | _LLU(_ios_obj(ios, dev)->id), | 869 | _LLU(_ios_obj(ios, cur_comp)->id), |
870 | ios->out_attr_len, dev); | 870 | ios->out_attr_len, dev); |
871 | } | 871 | } |
872 | 872 | ||
diff --git a/fs/exofs/super.c b/fs/exofs/super.c index 433783624d1..dde41a75c7c 100644 --- a/fs/exofs/super.c +++ b/fs/exofs/super.c | |||
@@ -400,8 +400,6 @@ static int exofs_sync_fs(struct super_block *sb, int wait) | |||
400 | ret = ore_write(ios); | 400 | ret = ore_write(ios); |
401 | if (unlikely(ret)) | 401 | if (unlikely(ret)) |
402 | EXOFS_ERR("%s: ore_write failed.\n", __func__); | 402 | EXOFS_ERR("%s: ore_write failed.\n", __func__); |
403 | else | ||
404 | sb->s_dirt = 0; | ||
405 | 403 | ||
406 | 404 | ||
407 | unlock_super(sb); | 405 | unlock_super(sb); |
@@ -412,14 +410,6 @@ out: | |||
412 | return ret; | 410 | return ret; |
413 | } | 411 | } |
414 | 412 | ||
415 | static void exofs_write_super(struct super_block *sb) | ||
416 | { | ||
417 | if (!(sb->s_flags & MS_RDONLY)) | ||
418 | exofs_sync_fs(sb, 1); | ||
419 | else | ||
420 | sb->s_dirt = 0; | ||
421 | } | ||
422 | |||
423 | static void _exofs_print_device(const char *msg, const char *dev_path, | 413 | static void _exofs_print_device(const char *msg, const char *dev_path, |
424 | struct osd_dev *od, u64 pid) | 414 | struct osd_dev *od, u64 pid) |
425 | { | 415 | { |
@@ -952,7 +942,6 @@ static const struct super_operations exofs_sops = { | |||
952 | .write_inode = exofs_write_inode, | 942 | .write_inode = exofs_write_inode, |
953 | .evict_inode = exofs_evict_inode, | 943 | .evict_inode = exofs_evict_inode, |
954 | .put_super = exofs_put_super, | 944 | .put_super = exofs_put_super, |
955 | .write_super = exofs_write_super, | ||
956 | .sync_fs = exofs_sync_fs, | 945 | .sync_fs = exofs_sync_fs, |
957 | .statfs = exofs_statfs, | 946 | .statfs = exofs_statfs, |
958 | }; | 947 | }; |
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index 9a4a5c48b1c..a07597307fd 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c | |||
@@ -3459,14 +3459,6 @@ ext3_reserve_inode_write(handle_t *handle, struct inode *inode, | |||
3459 | * inode out, but prune_icache isn't a user-visible syncing function. | 3459 | * inode out, but prune_icache isn't a user-visible syncing function. |
3460 | * Whenever the user wants stuff synced (sys_sync, sys_msync, sys_fsync) | 3460 | * Whenever the user wants stuff synced (sys_sync, sys_msync, sys_fsync) |
3461 | * we start and wait on commits. | 3461 | * we start and wait on commits. |
3462 | * | ||
3463 | * Is this efficient/effective? Well, we're being nice to the system | ||
3464 | * by cleaning up our inodes proactively so they can be reaped | ||
3465 | * without I/O. But we are potentially leaving up to five seconds' | ||
3466 | * worth of inodes floating about which prune_icache wants us to | ||
3467 | * write out. One way to fix that would be to get prune_icache() | ||
3468 | * to do a write_super() to free up some memory. It has the desired | ||
3469 | * effect. | ||
3470 | */ | 3462 | */ |
3471 | int ext3_mark_inode_dirty(handle_t *handle, struct inode *inode) | 3463 | int ext3_mark_inode_dirty(handle_t *handle, struct inode *inode) |
3472 | { | 3464 | { |
diff --git a/fs/ext3/super.c b/fs/ext3/super.c index ff9bcdc5b0d..8c892e93d8e 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c | |||
@@ -64,11 +64,6 @@ static int ext3_freeze(struct super_block *sb); | |||
64 | 64 | ||
65 | /* | 65 | /* |
66 | * Wrappers for journal_start/end. | 66 | * Wrappers for journal_start/end. |
67 | * | ||
68 | * The only special thing we need to do here is to make sure that all | ||
69 | * journal_end calls result in the superblock being marked dirty, so | ||
70 | * that sync() will call the filesystem's write_super callback if | ||
71 | * appropriate. | ||
72 | */ | 67 | */ |
73 | handle_t *ext3_journal_start_sb(struct super_block *sb, int nblocks) | 68 | handle_t *ext3_journal_start_sb(struct super_block *sb, int nblocks) |
74 | { | 69 | { |
@@ -90,12 +85,6 @@ handle_t *ext3_journal_start_sb(struct super_block *sb, int nblocks) | |||
90 | return journal_start(journal, nblocks); | 85 | return journal_start(journal, nblocks); |
91 | } | 86 | } |
92 | 87 | ||
93 | /* | ||
94 | * The only special thing we need to do here is to make sure that all | ||
95 | * journal_stop calls result in the superblock being marked dirty, so | ||
96 | * that sync() will call the filesystem's write_super callback if | ||
97 | * appropriate. | ||
98 | */ | ||
99 | int __ext3_journal_stop(const char *where, handle_t *handle) | 88 | int __ext3_journal_stop(const char *where, handle_t *handle) |
100 | { | 89 | { |
101 | struct super_block *sb; | 90 | struct super_block *sb; |
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c index d23b31ca9d7..1b5089067d0 100644 --- a/fs/ext4/balloc.c +++ b/fs/ext4/balloc.c | |||
@@ -280,14 +280,18 @@ struct ext4_group_desc * ext4_get_group_desc(struct super_block *sb, | |||
280 | return desc; | 280 | return desc; |
281 | } | 281 | } |
282 | 282 | ||
283 | static int ext4_valid_block_bitmap(struct super_block *sb, | 283 | /* |
284 | struct ext4_group_desc *desc, | 284 | * Return the block number which was discovered to be invalid, or 0 if |
285 | unsigned int block_group, | 285 | * the block bitmap is valid. |
286 | struct buffer_head *bh) | 286 | */ |
287 | static ext4_fsblk_t ext4_valid_block_bitmap(struct super_block *sb, | ||
288 | struct ext4_group_desc *desc, | ||
289 | unsigned int block_group, | ||
290 | struct buffer_head *bh) | ||
287 | { | 291 | { |
288 | ext4_grpblk_t offset; | 292 | ext4_grpblk_t offset; |
289 | ext4_grpblk_t next_zero_bit; | 293 | ext4_grpblk_t next_zero_bit; |
290 | ext4_fsblk_t bitmap_blk; | 294 | ext4_fsblk_t blk; |
291 | ext4_fsblk_t group_first_block; | 295 | ext4_fsblk_t group_first_block; |
292 | 296 | ||
293 | if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG)) { | 297 | if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG)) { |
@@ -297,37 +301,33 @@ static int ext4_valid_block_bitmap(struct super_block *sb, | |||
297 | * or it has to also read the block group where the bitmaps | 301 | * or it has to also read the block group where the bitmaps |
298 | * are located to verify they are set. | 302 | * are located to verify they are set. |
299 | */ | 303 | */ |
300 | return 1; | 304 | return 0; |
301 | } | 305 | } |
302 | group_first_block = ext4_group_first_block_no(sb, block_group); | 306 | group_first_block = ext4_group_first_block_no(sb, block_group); |
303 | 307 | ||
304 | /* check whether block bitmap block number is set */ | 308 | /* check whether block bitmap block number is set */ |
305 | bitmap_blk = ext4_block_bitmap(sb, desc); | 309 | blk = ext4_block_bitmap(sb, desc); |
306 | offset = bitmap_blk - group_first_block; | 310 | offset = blk - group_first_block; |
307 | if (!ext4_test_bit(offset, bh->b_data)) | 311 | if (!ext4_test_bit(offset, bh->b_data)) |
308 | /* bad block bitmap */ | 312 | /* bad block bitmap */ |
309 | goto err_out; | 313 | return blk; |
310 | 314 | ||
311 | /* check whether the inode bitmap block number is set */ | 315 | /* check whether the inode bitmap block number is set */ |
312 | bitmap_blk = ext4_inode_bitmap(sb, desc); | 316 | blk = ext4_inode_bitmap(sb, desc); |
313 | offset = bitmap_blk - group_first_block; | 317 | offset = blk - group_first_block; |
314 | if (!ext4_test_bit(offset, bh->b_data)) | 318 | if (!ext4_test_bit(offset, bh->b_data)) |
315 | /* bad block bitmap */ | 319 | /* bad block bitmap */ |
316 | goto err_out; | 320 | return blk; |
317 | 321 | ||
318 | /* check whether the inode table block number is set */ | 322 | /* check whether the inode table block number is set */ |
319 | bitmap_blk = ext4_inode_table(sb, desc); | 323 | blk = ext4_inode_table(sb, desc); |
320 | offset = bitmap_blk - group_first_block; | 324 | offset = blk - group_first_block; |
321 | next_zero_bit = ext4_find_next_zero_bit(bh->b_data, | 325 | next_zero_bit = ext4_find_next_zero_bit(bh->b_data, |
322 | offset + EXT4_SB(sb)->s_itb_per_group, | 326 | offset + EXT4_SB(sb)->s_itb_per_group, |
323 | offset); | 327 | offset); |
324 | if (next_zero_bit >= offset + EXT4_SB(sb)->s_itb_per_group) | 328 | if (next_zero_bit < offset + EXT4_SB(sb)->s_itb_per_group) |
325 | /* good bitmap for inode tables */ | 329 | /* bad bitmap for inode tables */ |
326 | return 1; | 330 | return blk; |
327 | |||
328 | err_out: | ||
329 | ext4_error(sb, "Invalid block bitmap - block_group = %d, block = %llu", | ||
330 | block_group, bitmap_blk); | ||
331 | return 0; | 331 | return 0; |
332 | } | 332 | } |
333 | 333 | ||
@@ -336,14 +336,26 @@ void ext4_validate_block_bitmap(struct super_block *sb, | |||
336 | unsigned int block_group, | 336 | unsigned int block_group, |
337 | struct buffer_head *bh) | 337 | struct buffer_head *bh) |
338 | { | 338 | { |
339 | ext4_fsblk_t blk; | ||
340 | |||
339 | if (buffer_verified(bh)) | 341 | if (buffer_verified(bh)) |
340 | return; | 342 | return; |
341 | 343 | ||
342 | ext4_lock_group(sb, block_group); | 344 | ext4_lock_group(sb, block_group); |
343 | if (ext4_valid_block_bitmap(sb, desc, block_group, bh) && | 345 | blk = ext4_valid_block_bitmap(sb, desc, block_group, bh); |
344 | ext4_block_bitmap_csum_verify(sb, block_group, desc, bh, | 346 | if (unlikely(blk != 0)) { |
345 | EXT4_BLOCKS_PER_GROUP(sb) / 8)) | 347 | ext4_unlock_group(sb, block_group); |
346 | set_buffer_verified(bh); | 348 | ext4_error(sb, "bg %u: block %llu: invalid block bitmap", |
349 | block_group, blk); | ||
350 | return; | ||
351 | } | ||
352 | if (unlikely(!ext4_block_bitmap_csum_verify(sb, block_group, | ||
353 | desc, bh, EXT4_BLOCKS_PER_GROUP(sb) / 8))) { | ||
354 | ext4_unlock_group(sb, block_group); | ||
355 | ext4_error(sb, "bg %u: bad block bitmap checksum", block_group); | ||
356 | return; | ||
357 | } | ||
358 | set_buffer_verified(bh); | ||
347 | ext4_unlock_group(sb, block_group); | 359 | ext4_unlock_group(sb, block_group); |
348 | } | 360 | } |
349 | 361 | ||
diff --git a/fs/ext4/bitmap.c b/fs/ext4/bitmap.c index f8716eab999..5c2d1813ebe 100644 --- a/fs/ext4/bitmap.c +++ b/fs/ext4/bitmap.c | |||
@@ -79,7 +79,6 @@ int ext4_block_bitmap_csum_verify(struct super_block *sb, ext4_group_t group, | |||
79 | if (provided == calculated) | 79 | if (provided == calculated) |
80 | return 1; | 80 | return 1; |
81 | 81 | ||
82 | ext4_error(sb, "Bad block bitmap checksum: block_group = %u", group); | ||
83 | return 0; | 82 | return 0; |
84 | } | 83 | } |
85 | 84 | ||
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index cd0c7ed0677..aabbb3f5368 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c | |||
@@ -2662,6 +2662,7 @@ cont: | |||
2662 | } | 2662 | } |
2663 | path[0].p_depth = depth; | 2663 | path[0].p_depth = depth; |
2664 | path[0].p_hdr = ext_inode_hdr(inode); | 2664 | path[0].p_hdr = ext_inode_hdr(inode); |
2665 | i = 0; | ||
2665 | 2666 | ||
2666 | if (ext4_ext_check(inode, path[0].p_hdr, depth)) { | 2667 | if (ext4_ext_check(inode, path[0].p_hdr, depth)) { |
2667 | err = -EIO; | 2668 | err = -EIO; |
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 6324f74e034..dff171c3a12 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -1970,7 +1970,7 @@ static void ext4_end_io_buffer_write(struct buffer_head *bh, int uptodate); | |||
1970 | * This function can get called via... | 1970 | * This function can get called via... |
1971 | * - ext4_da_writepages after taking page lock (have journal handle) | 1971 | * - ext4_da_writepages after taking page lock (have journal handle) |
1972 | * - journal_submit_inode_data_buffers (no journal handle) | 1972 | * - journal_submit_inode_data_buffers (no journal handle) |
1973 | * - shrink_page_list via pdflush (no journal handle) | 1973 | * - shrink_page_list via the kswapd/direct reclaim (no journal handle) |
1974 | * - grab_page_cache when doing write_begin (have journal handle) | 1974 | * - grab_page_cache when doing write_begin (have journal handle) |
1975 | * | 1975 | * |
1976 | * We don't do any block allocation in this function. If we have page with | 1976 | * We don't do any block allocation in this function. If we have page with |
@@ -4589,14 +4589,6 @@ static int ext4_expand_extra_isize(struct inode *inode, | |||
4589 | * inode out, but prune_icache isn't a user-visible syncing function. | 4589 | * inode out, but prune_icache isn't a user-visible syncing function. |
4590 | * Whenever the user wants stuff synced (sys_sync, sys_msync, sys_fsync) | 4590 | * Whenever the user wants stuff synced (sys_sync, sys_msync, sys_fsync) |
4591 | * we start and wait on commits. | 4591 | * we start and wait on commits. |
4592 | * | ||
4593 | * Is this efficient/effective? Well, we're being nice to the system | ||
4594 | * by cleaning up our inodes proactively so they can be reaped | ||
4595 | * without I/O. But we are potentially leaving up to five seconds' | ||
4596 | * worth of inodes floating about which prune_icache wants us to | ||
4597 | * write out. One way to fix that would be to get prune_icache() | ||
4598 | * to do a write_super() to free up some memory. It has the desired | ||
4599 | * effect. | ||
4600 | */ | 4592 | */ |
4601 | int ext4_mark_inode_dirty(handle_t *handle, struct inode *inode) | 4593 | int ext4_mark_inode_dirty(handle_t *handle, struct inode *inode) |
4602 | { | 4594 | { |
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index d76ec8277d3..c6e0cb3d1f4 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
@@ -326,11 +326,6 @@ static void ext4_put_nojournal(handle_t *handle) | |||
326 | 326 | ||
327 | /* | 327 | /* |
328 | * Wrappers for jbd2_journal_start/end. | 328 | * Wrappers for jbd2_journal_start/end. |
329 | * | ||
330 | * The only special thing we need to do here is to make sure that all | ||
331 | * journal_end calls result in the superblock being marked dirty, so | ||
332 | * that sync() will call the filesystem's write_super callback if | ||
333 | * appropriate. | ||
334 | */ | 329 | */ |
335 | handle_t *ext4_journal_start_sb(struct super_block *sb, int nblocks) | 330 | handle_t *ext4_journal_start_sb(struct super_block *sb, int nblocks) |
336 | { | 331 | { |
@@ -356,12 +351,6 @@ handle_t *ext4_journal_start_sb(struct super_block *sb, int nblocks) | |||
356 | return jbd2_journal_start(journal, nblocks); | 351 | return jbd2_journal_start(journal, nblocks); |
357 | } | 352 | } |
358 | 353 | ||
359 | /* | ||
360 | * The only special thing we need to do here is to make sure that all | ||
361 | * jbd2_journal_stop calls result in the superblock being marked dirty, so | ||
362 | * that sync() will call the filesystem's write_super callback if | ||
363 | * appropriate. | ||
364 | */ | ||
365 | int __ext4_journal_stop(const char *where, unsigned int line, handle_t *handle) | 354 | int __ext4_journal_stop(const char *where, unsigned int line, handle_t *handle) |
366 | { | 355 | { |
367 | struct super_block *sb; | 356 | struct super_block *sb; |
@@ -959,6 +948,7 @@ static struct inode *ext4_alloc_inode(struct super_block *sb) | |||
959 | ei->i_reserved_meta_blocks = 0; | 948 | ei->i_reserved_meta_blocks = 0; |
960 | ei->i_allocated_meta_blocks = 0; | 949 | ei->i_allocated_meta_blocks = 0; |
961 | ei->i_da_metadata_calc_len = 0; | 950 | ei->i_da_metadata_calc_len = 0; |
951 | ei->i_da_metadata_calc_last_lblock = 0; | ||
962 | spin_lock_init(&(ei->i_block_reservation_lock)); | 952 | spin_lock_init(&(ei->i_block_reservation_lock)); |
963 | #ifdef CONFIG_QUOTA | 953 | #ifdef CONFIG_QUOTA |
964 | ei->i_reserved_quota = 0; | 954 | ei->i_reserved_quota = 0; |
@@ -3119,6 +3109,10 @@ static int count_overhead(struct super_block *sb, ext4_group_t grp, | |||
3119 | ext4_group_t i, ngroups = ext4_get_groups_count(sb); | 3109 | ext4_group_t i, ngroups = ext4_get_groups_count(sb); |
3120 | int s, j, count = 0; | 3110 | int s, j, count = 0; |
3121 | 3111 | ||
3112 | if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_BIGALLOC)) | ||
3113 | return (ext4_bg_has_super(sb, grp) + ext4_bg_num_gdb(sb, grp) + | ||
3114 | sbi->s_itb_per_group + 2); | ||
3115 | |||
3122 | first_block = le32_to_cpu(sbi->s_es->s_first_data_block) + | 3116 | first_block = le32_to_cpu(sbi->s_es->s_first_data_block) + |
3123 | (grp * EXT4_BLOCKS_PER_GROUP(sb)); | 3117 | (grp * EXT4_BLOCKS_PER_GROUP(sb)); |
3124 | last_block = first_block + EXT4_BLOCKS_PER_GROUP(sb) - 1; | 3118 | last_block = first_block + EXT4_BLOCKS_PER_GROUP(sb) - 1; |
@@ -4430,6 +4424,7 @@ static void ext4_clear_journal_err(struct super_block *sb, | |||
4430 | ext4_commit_super(sb, 1); | 4424 | ext4_commit_super(sb, 1); |
4431 | 4425 | ||
4432 | jbd2_journal_clear_err(journal); | 4426 | jbd2_journal_clear_err(journal); |
4427 | jbd2_journal_update_sb_errno(journal); | ||
4433 | } | 4428 | } |
4434 | } | 4429 | } |
4435 | 4430 | ||
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 8964cf3999b..324bc085053 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c | |||
@@ -383,6 +383,9 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, | |||
383 | struct fuse_entry_out outentry; | 383 | struct fuse_entry_out outentry; |
384 | struct fuse_file *ff; | 384 | struct fuse_file *ff; |
385 | 385 | ||
386 | /* Userspace expects S_IFREG in create mode */ | ||
387 | BUG_ON((mode & S_IFMT) != S_IFREG); | ||
388 | |||
386 | forget = fuse_alloc_forget(); | 389 | forget = fuse_alloc_forget(); |
387 | err = -ENOMEM; | 390 | err = -ENOMEM; |
388 | if (!forget) | 391 | if (!forget) |
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 93d8d6c9494..aba15f1b7ad 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c | |||
@@ -703,13 +703,16 @@ static ssize_t fuse_file_aio_read(struct kiocb *iocb, const struct iovec *iov, | |||
703 | unsigned long nr_segs, loff_t pos) | 703 | unsigned long nr_segs, loff_t pos) |
704 | { | 704 | { |
705 | struct inode *inode = iocb->ki_filp->f_mapping->host; | 705 | struct inode *inode = iocb->ki_filp->f_mapping->host; |
706 | struct fuse_conn *fc = get_fuse_conn(inode); | ||
706 | 707 | ||
707 | if (pos + iov_length(iov, nr_segs) > i_size_read(inode)) { | 708 | /* |
709 | * In auto invalidate mode, always update attributes on read. | ||
710 | * Otherwise, only update if we attempt to read past EOF (to ensure | ||
711 | * i_size is up to date). | ||
712 | */ | ||
713 | if (fc->auto_inval_data || | ||
714 | (pos + iov_length(iov, nr_segs) > i_size_read(inode))) { | ||
708 | int err; | 715 | int err; |
709 | /* | ||
710 | * If trying to read past EOF, make sure the i_size | ||
711 | * attribute is up-to-date. | ||
712 | */ | ||
713 | err = fuse_update_attributes(inode, NULL, iocb->ki_filp, NULL); | 716 | err = fuse_update_attributes(inode, NULL, iocb->ki_filp, NULL); |
714 | if (err) | 717 | if (err) |
715 | return err; | 718 | return err; |
@@ -1700,7 +1703,7 @@ static int fuse_verify_ioctl_iov(struct iovec *iov, size_t count) | |||
1700 | size_t n; | 1703 | size_t n; |
1701 | u32 max = FUSE_MAX_PAGES_PER_REQ << PAGE_SHIFT; | 1704 | u32 max = FUSE_MAX_PAGES_PER_REQ << PAGE_SHIFT; |
1702 | 1705 | ||
1703 | for (n = 0; n < count; n++) { | 1706 | for (n = 0; n < count; n++, iov++) { |
1704 | if (iov->iov_len > (size_t) max) | 1707 | if (iov->iov_len > (size_t) max) |
1705 | return -ENOMEM; | 1708 | return -ENOMEM; |
1706 | max -= iov->iov_len; | 1709 | max -= iov->iov_len; |
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index 771fb6322c0..e24dd74e306 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h | |||
@@ -484,6 +484,9 @@ struct fuse_conn { | |||
484 | /** Is fallocate not implemented by fs? */ | 484 | /** Is fallocate not implemented by fs? */ |
485 | unsigned no_fallocate:1; | 485 | unsigned no_fallocate:1; |
486 | 486 | ||
487 | /** Use enhanced/automatic page cache invalidation. */ | ||
488 | unsigned auto_inval_data:1; | ||
489 | |||
487 | /** The number of requests waiting for completion */ | 490 | /** The number of requests waiting for completion */ |
488 | atomic_t num_waiting; | 491 | atomic_t num_waiting; |
489 | 492 | ||
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 1cd61652018..ce0a2838ccd 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c | |||
@@ -197,6 +197,7 @@ void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr, | |||
197 | struct fuse_conn *fc = get_fuse_conn(inode); | 197 | struct fuse_conn *fc = get_fuse_conn(inode); |
198 | struct fuse_inode *fi = get_fuse_inode(inode); | 198 | struct fuse_inode *fi = get_fuse_inode(inode); |
199 | loff_t oldsize; | 199 | loff_t oldsize; |
200 | struct timespec old_mtime; | ||
200 | 201 | ||
201 | spin_lock(&fc->lock); | 202 | spin_lock(&fc->lock); |
202 | if (attr_version != 0 && fi->attr_version > attr_version) { | 203 | if (attr_version != 0 && fi->attr_version > attr_version) { |
@@ -204,15 +205,35 @@ void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr, | |||
204 | return; | 205 | return; |
205 | } | 206 | } |
206 | 207 | ||
208 | old_mtime = inode->i_mtime; | ||
207 | fuse_change_attributes_common(inode, attr, attr_valid); | 209 | fuse_change_attributes_common(inode, attr, attr_valid); |
208 | 210 | ||
209 | oldsize = inode->i_size; | 211 | oldsize = inode->i_size; |
210 | i_size_write(inode, attr->size); | 212 | i_size_write(inode, attr->size); |
211 | spin_unlock(&fc->lock); | 213 | spin_unlock(&fc->lock); |
212 | 214 | ||
213 | if (S_ISREG(inode->i_mode) && oldsize != attr->size) { | 215 | if (S_ISREG(inode->i_mode)) { |
214 | truncate_pagecache(inode, oldsize, attr->size); | 216 | bool inval = false; |
215 | invalidate_inode_pages2(inode->i_mapping); | 217 | |
218 | if (oldsize != attr->size) { | ||
219 | truncate_pagecache(inode, oldsize, attr->size); | ||
220 | inval = true; | ||
221 | } else if (fc->auto_inval_data) { | ||
222 | struct timespec new_mtime = { | ||
223 | .tv_sec = attr->mtime, | ||
224 | .tv_nsec = attr->mtimensec, | ||
225 | }; | ||
226 | |||
227 | /* | ||
228 | * Auto inval mode also checks and invalidates if mtime | ||
229 | * has changed. | ||
230 | */ | ||
231 | if (!timespec_equal(&old_mtime, &new_mtime)) | ||
232 | inval = true; | ||
233 | } | ||
234 | |||
235 | if (inval) | ||
236 | invalidate_inode_pages2(inode->i_mapping); | ||
216 | } | 237 | } |
217 | } | 238 | } |
218 | 239 | ||
@@ -834,6 +855,8 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req) | |||
834 | fc->big_writes = 1; | 855 | fc->big_writes = 1; |
835 | if (arg->flags & FUSE_DONT_MASK) | 856 | if (arg->flags & FUSE_DONT_MASK) |
836 | fc->dont_mask = 1; | 857 | fc->dont_mask = 1; |
858 | if (arg->flags & FUSE_AUTO_INVAL_DATA) | ||
859 | fc->auto_inval_data = 1; | ||
837 | } else { | 860 | } else { |
838 | ra_pages = fc->max_read / PAGE_CACHE_SIZE; | 861 | ra_pages = fc->max_read / PAGE_CACHE_SIZE; |
839 | fc->no_lock = 1; | 862 | fc->no_lock = 1; |
@@ -859,7 +882,8 @@ static void fuse_send_init(struct fuse_conn *fc, struct fuse_req *req) | |||
859 | arg->max_readahead = fc->bdi.ra_pages * PAGE_CACHE_SIZE; | 882 | arg->max_readahead = fc->bdi.ra_pages * PAGE_CACHE_SIZE; |
860 | arg->flags |= FUSE_ASYNC_READ | FUSE_POSIX_LOCKS | FUSE_ATOMIC_O_TRUNC | | 883 | arg->flags |= FUSE_ASYNC_READ | FUSE_POSIX_LOCKS | FUSE_ATOMIC_O_TRUNC | |
861 | FUSE_EXPORT_SUPPORT | FUSE_BIG_WRITES | FUSE_DONT_MASK | | 884 | FUSE_EXPORT_SUPPORT | FUSE_BIG_WRITES | FUSE_DONT_MASK | |
862 | FUSE_FLOCK_LOCKS; | 885 | FUSE_SPLICE_WRITE | FUSE_SPLICE_MOVE | FUSE_SPLICE_READ | |
886 | FUSE_FLOCK_LOCKS | FUSE_IOCTL_DIR | FUSE_AUTO_INVAL_DATA; | ||
863 | req->in.h.opcode = FUSE_INIT; | 887 | req->in.h.opcode = FUSE_INIT; |
864 | req->in.numargs = 1; | 888 | req->in.numargs = 1; |
865 | req->in.args[0].size = sizeof(*arg); | 889 | req->in.args[0].size = sizeof(*arg); |
diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c index 3a56c8d94de..22255d96b27 100644 --- a/fs/gfs2/meta_io.c +++ b/fs/gfs2/meta_io.c | |||
@@ -52,7 +52,7 @@ static int gfs2_aspace_writepage(struct page *page, struct writeback_control *wb | |||
52 | /* | 52 | /* |
53 | * If it's a fully non-blocking write attempt and we cannot | 53 | * If it's a fully non-blocking write attempt and we cannot |
54 | * lock the buffer then redirty the page. Note that this can | 54 | * lock the buffer then redirty the page. Note that this can |
55 | * potentially cause a busy-wait loop from pdflush and kswapd | 55 | * potentially cause a busy-wait loop from flusher thread and kswapd |
56 | * activity, but those code paths have their own higher-level | 56 | * activity, but those code paths have their own higher-level |
57 | * throttling. | 57 | * throttling. |
58 | */ | 58 | */ |
diff --git a/fs/hfs/mdb.c b/fs/hfs/mdb.c index 5fd51a5833f..b7ec224910c 100644 --- a/fs/hfs/mdb.c +++ b/fs/hfs/mdb.c | |||
@@ -236,10 +236,10 @@ out: | |||
236 | * hfs_mdb_commit() | 236 | * hfs_mdb_commit() |
237 | * | 237 | * |
238 | * Description: | 238 | * Description: |
239 | * This updates the MDB on disk (look also at hfs_write_super()). | 239 | * This updates the MDB on disk. |
240 | * It does not check, if the superblock has been modified, or | 240 | * It does not check, if the superblock has been modified, or |
241 | * if the filesystem has been mounted read-only. It is mainly | 241 | * if the filesystem has been mounted read-only. It is mainly |
242 | * called by hfs_write_super() and hfs_btree_extend(). | 242 | * called by hfs_sync_fs() and flush_mdb(). |
243 | * Input Variable(s): | 243 | * Input Variable(s): |
244 | * struct hfs_mdb *mdb: Pointer to the hfs MDB | 244 | * struct hfs_mdb *mdb: Pointer to the hfs MDB |
245 | * int backup; | 245 | * int backup; |
diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c index 425c2f2cf17..a2862339323 100644 --- a/fs/jbd/journal.c +++ b/fs/jbd/journal.c | |||
@@ -534,8 +534,8 @@ int journal_start_commit(journal_t *journal, tid_t *ptid) | |||
534 | ret = 1; | 534 | ret = 1; |
535 | } else if (journal->j_committing_transaction) { | 535 | } else if (journal->j_committing_transaction) { |
536 | /* | 536 | /* |
537 | * If ext3_write_super() recently started a commit, then we | 537 | * If commit has been started, then we have to wait for |
538 | * have to wait for completion of that transaction | 538 | * completion of that transaction. |
539 | */ | 539 | */ |
540 | if (ptid) | 540 | if (ptid) |
541 | *ptid = journal->j_committing_transaction->t_tid; | 541 | *ptid = journal->j_committing_transaction->t_tid; |
@@ -1113,6 +1113,11 @@ static void mark_journal_empty(journal_t *journal) | |||
1113 | 1113 | ||
1114 | BUG_ON(!mutex_is_locked(&journal->j_checkpoint_mutex)); | 1114 | BUG_ON(!mutex_is_locked(&journal->j_checkpoint_mutex)); |
1115 | spin_lock(&journal->j_state_lock); | 1115 | spin_lock(&journal->j_state_lock); |
1116 | /* Is it already empty? */ | ||
1117 | if (sb->s_start == 0) { | ||
1118 | spin_unlock(&journal->j_state_lock); | ||
1119 | return; | ||
1120 | } | ||
1116 | jbd_debug(1, "JBD: Marking journal as empty (seq %d)\n", | 1121 | jbd_debug(1, "JBD: Marking journal as empty (seq %d)\n", |
1117 | journal->j_tail_sequence); | 1122 | journal->j_tail_sequence); |
1118 | 1123 | ||
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index e9a3c4c8559..e149b99a7ff 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c | |||
@@ -612,8 +612,8 @@ int jbd2_journal_start_commit(journal_t *journal, tid_t *ptid) | |||
612 | ret = 1; | 612 | ret = 1; |
613 | } else if (journal->j_committing_transaction) { | 613 | } else if (journal->j_committing_transaction) { |
614 | /* | 614 | /* |
615 | * If ext3_write_super() recently started a commit, then we | 615 | * If commit has been started, then we have to wait for |
616 | * have to wait for completion of that transaction | 616 | * completion of that transaction. |
617 | */ | 617 | */ |
618 | if (ptid) | 618 | if (ptid) |
619 | *ptid = journal->j_committing_transaction->t_tid; | 619 | *ptid = journal->j_committing_transaction->t_tid; |
@@ -1377,7 +1377,7 @@ static void jbd2_mark_journal_empty(journal_t *journal) | |||
1377 | * Update a journal's errno. Write updated superblock to disk waiting for IO | 1377 | * Update a journal's errno. Write updated superblock to disk waiting for IO |
1378 | * to complete. | 1378 | * to complete. |
1379 | */ | 1379 | */ |
1380 | static void jbd2_journal_update_sb_errno(journal_t *journal) | 1380 | void jbd2_journal_update_sb_errno(journal_t *journal) |
1381 | { | 1381 | { |
1382 | journal_superblock_t *sb = journal->j_superblock; | 1382 | journal_superblock_t *sb = journal->j_superblock; |
1383 | 1383 | ||
@@ -1390,6 +1390,7 @@ static void jbd2_journal_update_sb_errno(journal_t *journal) | |||
1390 | 1390 | ||
1391 | jbd2_write_superblock(journal, WRITE_SYNC); | 1391 | jbd2_write_superblock(journal, WRITE_SYNC); |
1392 | } | 1392 | } |
1393 | EXPORT_SYMBOL(jbd2_journal_update_sb_errno); | ||
1393 | 1394 | ||
1394 | /* | 1395 | /* |
1395 | * Read the superblock for a given journal, performing initial | 1396 | * Read the superblock for a given journal, performing initial |
diff --git a/fs/namei.c b/fs/namei.c index 1b464390dde..dd1ed1b8e98 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -352,6 +352,7 @@ int __inode_permission(struct inode *inode, int mask) | |||
352 | /** | 352 | /** |
353 | * sb_permission - Check superblock-level permissions | 353 | * sb_permission - Check superblock-level permissions |
354 | * @sb: Superblock of inode to check permission on | 354 | * @sb: Superblock of inode to check permission on |
355 | * @inode: Inode to check permission on | ||
355 | * @mask: Right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC) | 356 | * @mask: Right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC) |
356 | * | 357 | * |
357 | * Separate out file-system wide checks from inode-specific permission checks. | 358 | * Separate out file-system wide checks from inode-specific permission checks. |
@@ -656,6 +657,7 @@ int sysctl_protected_hardlinks __read_mostly = 1; | |||
656 | /** | 657 | /** |
657 | * may_follow_link - Check symlink following for unsafe situations | 658 | * may_follow_link - Check symlink following for unsafe situations |
658 | * @link: The path of the symlink | 659 | * @link: The path of the symlink |
660 | * @nd: nameidata pathwalk data | ||
659 | * | 661 | * |
660 | * In the case of the sysctl_protected_symlinks sysctl being enabled, | 662 | * In the case of the sysctl_protected_symlinks sysctl being enabled, |
661 | * CAP_DAC_OVERRIDE needs to be specifically ignored if the symlink is | 663 | * CAP_DAC_OVERRIDE needs to be specifically ignored if the symlink is |
@@ -2414,7 +2416,7 @@ static int atomic_open(struct nameidata *nd, struct dentry *dentry, | |||
2414 | goto out; | 2416 | goto out; |
2415 | } | 2417 | } |
2416 | 2418 | ||
2417 | mode = op->mode & S_IALLUGO; | 2419 | mode = op->mode; |
2418 | if ((open_flag & O_CREAT) && !IS_POSIXACL(dir)) | 2420 | if ((open_flag & O_CREAT) && !IS_POSIXACL(dir)) |
2419 | mode &= ~current_umask(); | 2421 | mode &= ~current_umask(); |
2420 | 2422 | ||
@@ -2452,7 +2454,7 @@ static int atomic_open(struct nameidata *nd, struct dentry *dentry, | |||
2452 | } | 2454 | } |
2453 | 2455 | ||
2454 | if (open_flag & O_CREAT) { | 2456 | if (open_flag & O_CREAT) { |
2455 | error = may_o_create(&nd->path, dentry, op->mode); | 2457 | error = may_o_create(&nd->path, dentry, mode); |
2456 | if (error) { | 2458 | if (error) { |
2457 | create_error = error; | 2459 | create_error = error; |
2458 | if (open_flag & O_EXCL) | 2460 | if (open_flag & O_EXCL) |
@@ -2489,6 +2491,10 @@ static int atomic_open(struct nameidata *nd, struct dentry *dentry, | |||
2489 | dput(dentry); | 2491 | dput(dentry); |
2490 | dentry = file->f_path.dentry; | 2492 | dentry = file->f_path.dentry; |
2491 | } | 2493 | } |
2494 | if (create_error && dentry->d_inode == NULL) { | ||
2495 | error = create_error; | ||
2496 | goto out; | ||
2497 | } | ||
2492 | goto looked_up; | 2498 | goto looked_up; |
2493 | } | 2499 | } |
2494 | 2500 | ||
diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile index 8bf3a3f6925..b7db60897f9 100644 --- a/fs/nfs/Makefile +++ b/fs/nfs/Makefile | |||
@@ -12,19 +12,19 @@ nfs-$(CONFIG_ROOT_NFS) += nfsroot.o | |||
12 | nfs-$(CONFIG_SYSCTL) += sysctl.o | 12 | nfs-$(CONFIG_SYSCTL) += sysctl.o |
13 | nfs-$(CONFIG_NFS_FSCACHE) += fscache.o fscache-index.o | 13 | nfs-$(CONFIG_NFS_FSCACHE) += fscache.o fscache-index.o |
14 | 14 | ||
15 | obj-$(CONFIG_NFS_V2) += nfs2.o | 15 | obj-$(CONFIG_NFS_V2) += nfsv2.o |
16 | nfs2-y := nfs2super.o proc.o nfs2xdr.o | 16 | nfsv2-y := nfs2super.o proc.o nfs2xdr.o |
17 | 17 | ||
18 | obj-$(CONFIG_NFS_V3) += nfs3.o | 18 | obj-$(CONFIG_NFS_V3) += nfsv3.o |
19 | nfs3-y := nfs3super.o nfs3client.o nfs3proc.o nfs3xdr.o | 19 | nfsv3-y := nfs3super.o nfs3client.o nfs3proc.o nfs3xdr.o |
20 | nfs3-$(CONFIG_NFS_V3_ACL) += nfs3acl.o | 20 | nfsv3-$(CONFIG_NFS_V3_ACL) += nfs3acl.o |
21 | 21 | ||
22 | obj-$(CONFIG_NFS_V4) += nfs4.o | 22 | obj-$(CONFIG_NFS_V4) += nfsv4.o |
23 | nfs4-y := nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o nfs4super.o nfs4file.o \ | 23 | nfsv4-y := nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o nfs4super.o nfs4file.o \ |
24 | delegation.o idmap.o callback.o callback_xdr.o callback_proc.o \ | 24 | delegation.o idmap.o callback.o callback_xdr.o callback_proc.o \ |
25 | nfs4namespace.o nfs4getroot.o nfs4client.o | 25 | nfs4namespace.o nfs4getroot.o nfs4client.o |
26 | nfs4-$(CONFIG_SYSCTL) += nfs4sysctl.o | 26 | nfsv4-$(CONFIG_SYSCTL) += nfs4sysctl.o |
27 | nfs4-$(CONFIG_NFS_V4_1) += pnfs.o pnfs_dev.o | 27 | nfsv4-$(CONFIG_NFS_V4_1) += pnfs.o pnfs_dev.o |
28 | 28 | ||
29 | obj-$(CONFIG_PNFS_FILE_LAYOUT) += nfs_layout_nfsv41_files.o | 29 | obj-$(CONFIG_PNFS_FILE_LAYOUT) += nfs_layout_nfsv41_files.o |
30 | nfs_layout_nfsv41_files-y := nfs4filelayout.o nfs4filelayoutdev.o | 30 | nfs_layout_nfsv41_files-y := nfs4filelayout.o nfs4filelayoutdev.o |
diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 9fc0d9dfc91..99694442b93 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c | |||
@@ -105,7 +105,7 @@ struct nfs_subversion *get_nfs_version(unsigned int version) | |||
105 | 105 | ||
106 | if (IS_ERR(nfs)) { | 106 | if (IS_ERR(nfs)) { |
107 | mutex_lock(&nfs_version_mutex); | 107 | mutex_lock(&nfs_version_mutex); |
108 | request_module("nfs%d", version); | 108 | request_module("nfsv%d", version); |
109 | nfs = find_nfs_version(version); | 109 | nfs = find_nfs_version(version); |
110 | mutex_unlock(&nfs_version_mutex); | 110 | mutex_unlock(&nfs_version_mutex); |
111 | } | 111 | } |
diff --git a/fs/nfs/idmap.c b/fs/nfs/idmap.c index b701358c39c..a850079467d 100644 --- a/fs/nfs/idmap.c +++ b/fs/nfs/idmap.c | |||
@@ -61,6 +61,12 @@ struct idmap { | |||
61 | struct mutex idmap_mutex; | 61 | struct mutex idmap_mutex; |
62 | }; | 62 | }; |
63 | 63 | ||
64 | struct idmap_legacy_upcalldata { | ||
65 | struct rpc_pipe_msg pipe_msg; | ||
66 | struct idmap_msg idmap_msg; | ||
67 | struct idmap *idmap; | ||
68 | }; | ||
69 | |||
64 | /** | 70 | /** |
65 | * nfs_fattr_init_names - initialise the nfs_fattr owner_name/group_name fields | 71 | * nfs_fattr_init_names - initialise the nfs_fattr owner_name/group_name fields |
66 | * @fattr: fully initialised struct nfs_fattr | 72 | * @fattr: fully initialised struct nfs_fattr |
@@ -324,6 +330,7 @@ static ssize_t nfs_idmap_get_key(const char *name, size_t namelen, | |||
324 | ret = nfs_idmap_request_key(&key_type_id_resolver_legacy, | 330 | ret = nfs_idmap_request_key(&key_type_id_resolver_legacy, |
325 | name, namelen, type, data, | 331 | name, namelen, type, data, |
326 | data_size, idmap); | 332 | data_size, idmap); |
333 | idmap->idmap_key_cons = NULL; | ||
327 | mutex_unlock(&idmap->idmap_mutex); | 334 | mutex_unlock(&idmap->idmap_mutex); |
328 | } | 335 | } |
329 | return ret; | 336 | return ret; |
@@ -380,11 +387,13 @@ static const match_table_t nfs_idmap_tokens = { | |||
380 | static int nfs_idmap_legacy_upcall(struct key_construction *, const char *, void *); | 387 | static int nfs_idmap_legacy_upcall(struct key_construction *, const char *, void *); |
381 | static ssize_t idmap_pipe_downcall(struct file *, const char __user *, | 388 | static ssize_t idmap_pipe_downcall(struct file *, const char __user *, |
382 | size_t); | 389 | size_t); |
390 | static void idmap_release_pipe(struct inode *); | ||
383 | static void idmap_pipe_destroy_msg(struct rpc_pipe_msg *); | 391 | static void idmap_pipe_destroy_msg(struct rpc_pipe_msg *); |
384 | 392 | ||
385 | static const struct rpc_pipe_ops idmap_upcall_ops = { | 393 | static const struct rpc_pipe_ops idmap_upcall_ops = { |
386 | .upcall = rpc_pipe_generic_upcall, | 394 | .upcall = rpc_pipe_generic_upcall, |
387 | .downcall = idmap_pipe_downcall, | 395 | .downcall = idmap_pipe_downcall, |
396 | .release_pipe = idmap_release_pipe, | ||
388 | .destroy_msg = idmap_pipe_destroy_msg, | 397 | .destroy_msg = idmap_pipe_destroy_msg, |
389 | }; | 398 | }; |
390 | 399 | ||
@@ -616,7 +625,8 @@ void nfs_idmap_quit(void) | |||
616 | nfs_idmap_quit_keyring(); | 625 | nfs_idmap_quit_keyring(); |
617 | } | 626 | } |
618 | 627 | ||
619 | static int nfs_idmap_prepare_message(char *desc, struct idmap_msg *im, | 628 | static int nfs_idmap_prepare_message(char *desc, struct idmap *idmap, |
629 | struct idmap_msg *im, | ||
620 | struct rpc_pipe_msg *msg) | 630 | struct rpc_pipe_msg *msg) |
621 | { | 631 | { |
622 | substring_t substr; | 632 | substring_t substr; |
@@ -659,6 +669,7 @@ static int nfs_idmap_legacy_upcall(struct key_construction *cons, | |||
659 | const char *op, | 669 | const char *op, |
660 | void *aux) | 670 | void *aux) |
661 | { | 671 | { |
672 | struct idmap_legacy_upcalldata *data; | ||
662 | struct rpc_pipe_msg *msg; | 673 | struct rpc_pipe_msg *msg; |
663 | struct idmap_msg *im; | 674 | struct idmap_msg *im; |
664 | struct idmap *idmap = (struct idmap *)aux; | 675 | struct idmap *idmap = (struct idmap *)aux; |
@@ -666,15 +677,15 @@ static int nfs_idmap_legacy_upcall(struct key_construction *cons, | |||
666 | int ret = -ENOMEM; | 677 | int ret = -ENOMEM; |
667 | 678 | ||
668 | /* msg and im are freed in idmap_pipe_destroy_msg */ | 679 | /* msg and im are freed in idmap_pipe_destroy_msg */ |
669 | msg = kmalloc(sizeof(*msg), GFP_KERNEL); | 680 | data = kmalloc(sizeof(*data), GFP_KERNEL); |
670 | if (!msg) | 681 | if (!data) |
671 | goto out0; | ||
672 | |||
673 | im = kmalloc(sizeof(*im), GFP_KERNEL); | ||
674 | if (!im) | ||
675 | goto out1; | 682 | goto out1; |
676 | 683 | ||
677 | ret = nfs_idmap_prepare_message(key->description, im, msg); | 684 | msg = &data->pipe_msg; |
685 | im = &data->idmap_msg; | ||
686 | data->idmap = idmap; | ||
687 | |||
688 | ret = nfs_idmap_prepare_message(key->description, idmap, im, msg); | ||
678 | if (ret < 0) | 689 | if (ret < 0) |
679 | goto out2; | 690 | goto out2; |
680 | 691 | ||
@@ -683,15 +694,15 @@ static int nfs_idmap_legacy_upcall(struct key_construction *cons, | |||
683 | 694 | ||
684 | ret = rpc_queue_upcall(idmap->idmap_pipe, msg); | 695 | ret = rpc_queue_upcall(idmap->idmap_pipe, msg); |
685 | if (ret < 0) | 696 | if (ret < 0) |
686 | goto out2; | 697 | goto out3; |
687 | 698 | ||
688 | return ret; | 699 | return ret; |
689 | 700 | ||
701 | out3: | ||
702 | idmap->idmap_key_cons = NULL; | ||
690 | out2: | 703 | out2: |
691 | kfree(im); | 704 | kfree(data); |
692 | out1: | 705 | out1: |
693 | kfree(msg); | ||
694 | out0: | ||
695 | complete_request_key(cons, ret); | 706 | complete_request_key(cons, ret); |
696 | return ret; | 707 | return ret; |
697 | } | 708 | } |
@@ -749,9 +760,8 @@ idmap_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) | |||
749 | } | 760 | } |
750 | 761 | ||
751 | if (!(im.im_status & IDMAP_STATUS_SUCCESS)) { | 762 | if (!(im.im_status & IDMAP_STATUS_SUCCESS)) { |
752 | ret = mlen; | 763 | ret = -ENOKEY; |
753 | complete_request_key(cons, -ENOKEY); | 764 | goto out; |
754 | goto out_incomplete; | ||
755 | } | 765 | } |
756 | 766 | ||
757 | namelen_in = strnlen(im.im_name, IDMAP_NAMESZ); | 767 | namelen_in = strnlen(im.im_name, IDMAP_NAMESZ); |
@@ -768,16 +778,32 @@ idmap_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) | |||
768 | 778 | ||
769 | out: | 779 | out: |
770 | complete_request_key(cons, ret); | 780 | complete_request_key(cons, ret); |
771 | out_incomplete: | ||
772 | return ret; | 781 | return ret; |
773 | } | 782 | } |
774 | 783 | ||
775 | static void | 784 | static void |
776 | idmap_pipe_destroy_msg(struct rpc_pipe_msg *msg) | 785 | idmap_pipe_destroy_msg(struct rpc_pipe_msg *msg) |
777 | { | 786 | { |
787 | struct idmap_legacy_upcalldata *data = container_of(msg, | ||
788 | struct idmap_legacy_upcalldata, | ||
789 | pipe_msg); | ||
790 | struct idmap *idmap = data->idmap; | ||
791 | struct key_construction *cons; | ||
792 | if (msg->errno) { | ||
793 | cons = ACCESS_ONCE(idmap->idmap_key_cons); | ||
794 | idmap->idmap_key_cons = NULL; | ||
795 | complete_request_key(cons, msg->errno); | ||
796 | } | ||
778 | /* Free memory allocated in nfs_idmap_legacy_upcall() */ | 797 | /* Free memory allocated in nfs_idmap_legacy_upcall() */ |
779 | kfree(msg->data); | 798 | kfree(data); |
780 | kfree(msg); | 799 | } |
800 | |||
801 | static void | ||
802 | idmap_release_pipe(struct inode *inode) | ||
803 | { | ||
804 | struct rpc_inode *rpci = RPC_I(inode); | ||
805 | struct idmap *idmap = (struct idmap *)rpci->private; | ||
806 | idmap->idmap_key_cons = NULL; | ||
781 | } | 807 | } |
782 | 808 | ||
783 | int nfs_map_name_to_uid(const struct nfs_server *server, const char *name, size_t namelen, __u32 *uid) | 809 | int nfs_map_name_to_uid(const struct nfs_server *server, const char *name, size_t namelen, __u32 *uid) |
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c index 0952c791df3..d6b3b5f2d77 100644 --- a/fs/nfs/nfs3proc.c +++ b/fs/nfs/nfs3proc.c | |||
@@ -69,7 +69,7 @@ do_proc_get_root(struct rpc_clnt *client, struct nfs_fh *fhandle, | |||
69 | nfs_fattr_init(info->fattr); | 69 | nfs_fattr_init(info->fattr); |
70 | status = rpc_call_sync(client, &msg, 0); | 70 | status = rpc_call_sync(client, &msg, 0); |
71 | dprintk("%s: reply fsinfo: %d\n", __func__, status); | 71 | dprintk("%s: reply fsinfo: %d\n", __func__, status); |
72 | if (!(info->fattr->valid & NFS_ATTR_FATTR)) { | 72 | if (status == 0 && !(info->fattr->valid & NFS_ATTR_FATTR)) { |
73 | msg.rpc_proc = &nfs3_procedures[NFS3PROC_GETATTR]; | 73 | msg.rpc_proc = &nfs3_procedures[NFS3PROC_GETATTR]; |
74 | msg.rpc_resp = info->fattr; | 74 | msg.rpc_resp = info->fattr; |
75 | status = rpc_call_sync(client, &msg, 0); | 75 | status = rpc_call_sync(client, &msg, 0); |
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index 3b950dd81e8..da0618aeead 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h | |||
@@ -205,6 +205,9 @@ extern const struct dentry_operations nfs4_dentry_operations; | |||
205 | int nfs_atomic_open(struct inode *, struct dentry *, struct file *, | 205 | int nfs_atomic_open(struct inode *, struct dentry *, struct file *, |
206 | unsigned, umode_t, int *); | 206 | unsigned, umode_t, int *); |
207 | 207 | ||
208 | /* super.c */ | ||
209 | extern struct file_system_type nfs4_fs_type; | ||
210 | |||
208 | /* nfs4namespace.c */ | 211 | /* nfs4namespace.c */ |
209 | rpc_authflavor_t nfs_find_best_sec(struct nfs4_secinfo_flavors *); | 212 | rpc_authflavor_t nfs_find_best_sec(struct nfs4_secinfo_flavors *); |
210 | struct rpc_clnt *nfs4_create_sec_client(struct rpc_clnt *, struct inode *, struct qstr *); | 213 | struct rpc_clnt *nfs4_create_sec_client(struct rpc_clnt *, struct inode *, struct qstr *); |
diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c index cbcdfaf3250..24eb663f8ed 100644 --- a/fs/nfs/nfs4client.c +++ b/fs/nfs/nfs4client.c | |||
@@ -74,7 +74,7 @@ struct nfs_client *nfs4_alloc_client(const struct nfs_client_initdata *cl_init) | |||
74 | return clp; | 74 | return clp; |
75 | 75 | ||
76 | error: | 76 | error: |
77 | kfree(clp); | 77 | nfs_free_client(clp); |
78 | return ERR_PTR(err); | 78 | return ERR_PTR(err); |
79 | } | 79 | } |
80 | 80 | ||
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index a99a8d94872..635274140b1 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -3737,9 +3737,10 @@ out: | |||
3737 | static void nfs4_write_cached_acl(struct inode *inode, struct page **pages, size_t pgbase, size_t acl_len) | 3737 | static void nfs4_write_cached_acl(struct inode *inode, struct page **pages, size_t pgbase, size_t acl_len) |
3738 | { | 3738 | { |
3739 | struct nfs4_cached_acl *acl; | 3739 | struct nfs4_cached_acl *acl; |
3740 | size_t buflen = sizeof(*acl) + acl_len; | ||
3740 | 3741 | ||
3741 | if (pages && acl_len <= PAGE_SIZE) { | 3742 | if (pages && buflen <= PAGE_SIZE) { |
3742 | acl = kmalloc(sizeof(*acl) + acl_len, GFP_KERNEL); | 3743 | acl = kmalloc(buflen, GFP_KERNEL); |
3743 | if (acl == NULL) | 3744 | if (acl == NULL) |
3744 | goto out; | 3745 | goto out; |
3745 | acl->cached = 1; | 3746 | acl->cached = 1; |
@@ -3819,7 +3820,7 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu | |||
3819 | if (ret) | 3820 | if (ret) |
3820 | goto out_free; | 3821 | goto out_free; |
3821 | 3822 | ||
3822 | acl_len = res.acl_len - res.acl_data_offset; | 3823 | acl_len = res.acl_len; |
3823 | if (acl_len > args.acl_len) | 3824 | if (acl_len > args.acl_len) |
3824 | nfs4_write_cached_acl(inode, NULL, 0, acl_len); | 3825 | nfs4_write_cached_acl(inode, NULL, 0, acl_len); |
3825 | else | 3826 | else |
@@ -6223,11 +6224,58 @@ static void nfs4_layoutget_done(struct rpc_task *task, void *calldata) | |||
6223 | dprintk("<-- %s\n", __func__); | 6224 | dprintk("<-- %s\n", __func__); |
6224 | } | 6225 | } |
6225 | 6226 | ||
6227 | static size_t max_response_pages(struct nfs_server *server) | ||
6228 | { | ||
6229 | u32 max_resp_sz = server->nfs_client->cl_session->fc_attrs.max_resp_sz; | ||
6230 | return nfs_page_array_len(0, max_resp_sz); | ||
6231 | } | ||
6232 | |||
6233 | static void nfs4_free_pages(struct page **pages, size_t size) | ||
6234 | { | ||
6235 | int i; | ||
6236 | |||
6237 | if (!pages) | ||
6238 | return; | ||
6239 | |||
6240 | for (i = 0; i < size; i++) { | ||
6241 | if (!pages[i]) | ||
6242 | break; | ||
6243 | __free_page(pages[i]); | ||
6244 | } | ||
6245 | kfree(pages); | ||
6246 | } | ||
6247 | |||
6248 | static struct page **nfs4_alloc_pages(size_t size, gfp_t gfp_flags) | ||
6249 | { | ||
6250 | struct page **pages; | ||
6251 | int i; | ||
6252 | |||
6253 | pages = kcalloc(size, sizeof(struct page *), gfp_flags); | ||
6254 | if (!pages) { | ||
6255 | dprintk("%s: can't alloc array of %zu pages\n", __func__, size); | ||
6256 | return NULL; | ||
6257 | } | ||
6258 | |||
6259 | for (i = 0; i < size; i++) { | ||
6260 | pages[i] = alloc_page(gfp_flags); | ||
6261 | if (!pages[i]) { | ||
6262 | dprintk("%s: failed to allocate page\n", __func__); | ||
6263 | nfs4_free_pages(pages, size); | ||
6264 | return NULL; | ||
6265 | } | ||
6266 | } | ||
6267 | |||
6268 | return pages; | ||
6269 | } | ||
6270 | |||
6226 | static void nfs4_layoutget_release(void *calldata) | 6271 | static void nfs4_layoutget_release(void *calldata) |
6227 | { | 6272 | { |
6228 | struct nfs4_layoutget *lgp = calldata; | 6273 | struct nfs4_layoutget *lgp = calldata; |
6274 | struct nfs_server *server = NFS_SERVER(lgp->args.inode); | ||
6275 | size_t max_pages = max_response_pages(server); | ||
6229 | 6276 | ||
6230 | dprintk("--> %s\n", __func__); | 6277 | dprintk("--> %s\n", __func__); |
6278 | nfs4_free_pages(lgp->args.layout.pages, max_pages); | ||
6231 | put_nfs_open_context(lgp->args.ctx); | 6279 | put_nfs_open_context(lgp->args.ctx); |
6232 | kfree(calldata); | 6280 | kfree(calldata); |
6233 | dprintk("<-- %s\n", __func__); | 6281 | dprintk("<-- %s\n", __func__); |
@@ -6239,9 +6287,10 @@ static const struct rpc_call_ops nfs4_layoutget_call_ops = { | |||
6239 | .rpc_release = nfs4_layoutget_release, | 6287 | .rpc_release = nfs4_layoutget_release, |
6240 | }; | 6288 | }; |
6241 | 6289 | ||
6242 | int nfs4_proc_layoutget(struct nfs4_layoutget *lgp) | 6290 | void nfs4_proc_layoutget(struct nfs4_layoutget *lgp, gfp_t gfp_flags) |
6243 | { | 6291 | { |
6244 | struct nfs_server *server = NFS_SERVER(lgp->args.inode); | 6292 | struct nfs_server *server = NFS_SERVER(lgp->args.inode); |
6293 | size_t max_pages = max_response_pages(server); | ||
6245 | struct rpc_task *task; | 6294 | struct rpc_task *task; |
6246 | struct rpc_message msg = { | 6295 | struct rpc_message msg = { |
6247 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LAYOUTGET], | 6296 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LAYOUTGET], |
@@ -6259,12 +6308,19 @@ int nfs4_proc_layoutget(struct nfs4_layoutget *lgp) | |||
6259 | 6308 | ||
6260 | dprintk("--> %s\n", __func__); | 6309 | dprintk("--> %s\n", __func__); |
6261 | 6310 | ||
6311 | lgp->args.layout.pages = nfs4_alloc_pages(max_pages, gfp_flags); | ||
6312 | if (!lgp->args.layout.pages) { | ||
6313 | nfs4_layoutget_release(lgp); | ||
6314 | return; | ||
6315 | } | ||
6316 | lgp->args.layout.pglen = max_pages * PAGE_SIZE; | ||
6317 | |||
6262 | lgp->res.layoutp = &lgp->args.layout; | 6318 | lgp->res.layoutp = &lgp->args.layout; |
6263 | lgp->res.seq_res.sr_slot = NULL; | 6319 | lgp->res.seq_res.sr_slot = NULL; |
6264 | nfs41_init_sequence(&lgp->args.seq_args, &lgp->res.seq_res, 0); | 6320 | nfs41_init_sequence(&lgp->args.seq_args, &lgp->res.seq_res, 0); |
6265 | task = rpc_run_task(&task_setup_data); | 6321 | task = rpc_run_task(&task_setup_data); |
6266 | if (IS_ERR(task)) | 6322 | if (IS_ERR(task)) |
6267 | return PTR_ERR(task); | 6323 | return; |
6268 | status = nfs4_wait_for_completion_rpc_task(task); | 6324 | status = nfs4_wait_for_completion_rpc_task(task); |
6269 | if (status == 0) | 6325 | if (status == 0) |
6270 | status = task->tk_status; | 6326 | status = task->tk_status; |
@@ -6272,7 +6328,7 @@ int nfs4_proc_layoutget(struct nfs4_layoutget *lgp) | |||
6272 | status = pnfs_layout_process(lgp); | 6328 | status = pnfs_layout_process(lgp); |
6273 | rpc_put_task(task); | 6329 | rpc_put_task(task); |
6274 | dprintk("<-- %s status=%d\n", __func__, status); | 6330 | dprintk("<-- %s status=%d\n", __func__, status); |
6275 | return status; | 6331 | return; |
6276 | } | 6332 | } |
6277 | 6333 | ||
6278 | static void | 6334 | static void |
@@ -6304,12 +6360,8 @@ static void nfs4_layoutreturn_done(struct rpc_task *task, void *calldata) | |||
6304 | return; | 6360 | return; |
6305 | } | 6361 | } |
6306 | spin_lock(&lo->plh_inode->i_lock); | 6362 | spin_lock(&lo->plh_inode->i_lock); |
6307 | if (task->tk_status == 0) { | 6363 | if (task->tk_status == 0 && lrp->res.lrs_present) |
6308 | if (lrp->res.lrs_present) { | 6364 | pnfs_set_layout_stateid(lo, &lrp->res.stateid, true); |
6309 | pnfs_set_layout_stateid(lo, &lrp->res.stateid, true); | ||
6310 | } else | ||
6311 | BUG_ON(!list_empty(&lo->plh_segs)); | ||
6312 | } | ||
6313 | lo->plh_block_lgets--; | 6365 | lo->plh_block_lgets--; |
6314 | spin_unlock(&lo->plh_inode->i_lock); | 6366 | spin_unlock(&lo->plh_inode->i_lock); |
6315 | dprintk("<-- %s\n", __func__); | 6367 | dprintk("<-- %s\n", __func__); |
diff --git a/fs/nfs/nfs4super.c b/fs/nfs/nfs4super.c index 12a31a9dbcd..bd61221ad2c 100644 --- a/fs/nfs/nfs4super.c +++ b/fs/nfs/nfs4super.c | |||
@@ -23,14 +23,6 @@ static struct dentry *nfs4_referral_mount(struct file_system_type *fs_type, | |||
23 | static struct dentry *nfs4_remote_referral_mount(struct file_system_type *fs_type, | 23 | static struct dentry *nfs4_remote_referral_mount(struct file_system_type *fs_type, |
24 | int flags, const char *dev_name, void *raw_data); | 24 | int flags, const char *dev_name, void *raw_data); |
25 | 25 | ||
26 | static struct file_system_type nfs4_fs_type = { | ||
27 | .owner = THIS_MODULE, | ||
28 | .name = "nfs4", | ||
29 | .mount = nfs_fs_mount, | ||
30 | .kill_sb = nfs_kill_super, | ||
31 | .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, | ||
32 | }; | ||
33 | |||
34 | static struct file_system_type nfs4_remote_fs_type = { | 26 | static struct file_system_type nfs4_remote_fs_type = { |
35 | .owner = THIS_MODULE, | 27 | .owner = THIS_MODULE, |
36 | .name = "nfs4", | 28 | .name = "nfs4", |
@@ -344,14 +336,8 @@ static int __init init_nfs_v4(void) | |||
344 | if (err) | 336 | if (err) |
345 | goto out1; | 337 | goto out1; |
346 | 338 | ||
347 | err = register_filesystem(&nfs4_fs_type); | ||
348 | if (err < 0) | ||
349 | goto out2; | ||
350 | |||
351 | register_nfs_version(&nfs_v4); | 339 | register_nfs_version(&nfs_v4); |
352 | return 0; | 340 | return 0; |
353 | out2: | ||
354 | nfs4_unregister_sysctl(); | ||
355 | out1: | 341 | out1: |
356 | nfs_idmap_quit(); | 342 | nfs_idmap_quit(); |
357 | out: | 343 | out: |
@@ -361,7 +347,6 @@ out: | |||
361 | static void __exit exit_nfs_v4(void) | 347 | static void __exit exit_nfs_v4(void) |
362 | { | 348 | { |
363 | unregister_nfs_version(&nfs_v4); | 349 | unregister_nfs_version(&nfs_v4); |
364 | unregister_filesystem(&nfs4_fs_type); | ||
365 | nfs4_unregister_sysctl(); | 350 | nfs4_unregister_sysctl(); |
366 | nfs_idmap_quit(); | 351 | nfs_idmap_quit(); |
367 | } | 352 | } |
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index ca13483edd6..1bfbd67c556 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
@@ -5045,22 +5045,19 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req, | |||
5045 | struct nfs_getaclres *res) | 5045 | struct nfs_getaclres *res) |
5046 | { | 5046 | { |
5047 | unsigned int savep; | 5047 | unsigned int savep; |
5048 | __be32 *bm_p; | ||
5049 | uint32_t attrlen, | 5048 | uint32_t attrlen, |
5050 | bitmap[3] = {0}; | 5049 | bitmap[3] = {0}; |
5051 | int status; | 5050 | int status; |
5052 | size_t page_len = xdr->buf->page_len; | 5051 | unsigned int pg_offset; |
5053 | 5052 | ||
5054 | res->acl_len = 0; | 5053 | res->acl_len = 0; |
5055 | if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0) | 5054 | if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0) |
5056 | goto out; | 5055 | goto out; |
5057 | 5056 | ||
5058 | bm_p = xdr->p; | 5057 | xdr_enter_page(xdr, xdr->buf->page_len); |
5059 | res->acl_data_offset = be32_to_cpup(bm_p) + 2; | 5058 | |
5060 | res->acl_data_offset <<= 2; | 5059 | /* Calculate the offset of the page data */ |
5061 | /* Check if the acl data starts beyond the allocated buffer */ | 5060 | pg_offset = xdr->buf->head[0].iov_len; |
5062 | if (res->acl_data_offset > page_len) | ||
5063 | return -ERANGE; | ||
5064 | 5061 | ||
5065 | if ((status = decode_attr_bitmap(xdr, bitmap)) != 0) | 5062 | if ((status = decode_attr_bitmap(xdr, bitmap)) != 0) |
5066 | goto out; | 5063 | goto out; |
@@ -5074,23 +5071,20 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req, | |||
5074 | /* The bitmap (xdr len + bitmaps) and the attr xdr len words | 5071 | /* The bitmap (xdr len + bitmaps) and the attr xdr len words |
5075 | * are stored with the acl data to handle the problem of | 5072 | * are stored with the acl data to handle the problem of |
5076 | * variable length bitmaps.*/ | 5073 | * variable length bitmaps.*/ |
5077 | xdr->p = bm_p; | 5074 | res->acl_data_offset = xdr_stream_pos(xdr) - pg_offset; |
5078 | 5075 | ||
5079 | /* We ignore &savep and don't do consistency checks on | 5076 | /* We ignore &savep and don't do consistency checks on |
5080 | * the attr length. Let userspace figure it out.... */ | 5077 | * the attr length. Let userspace figure it out.... */ |
5081 | attrlen += res->acl_data_offset; | 5078 | res->acl_len = attrlen; |
5082 | if (attrlen > page_len) { | 5079 | if (attrlen > (xdr->nwords << 2)) { |
5083 | if (res->acl_flags & NFS4_ACL_LEN_REQUEST) { | 5080 | if (res->acl_flags & NFS4_ACL_LEN_REQUEST) { |
5084 | /* getxattr interface called with a NULL buf */ | 5081 | /* getxattr interface called with a NULL buf */ |
5085 | res->acl_len = attrlen; | ||
5086 | goto out; | 5082 | goto out; |
5087 | } | 5083 | } |
5088 | dprintk("NFS: acl reply: attrlen %u > page_len %zu\n", | 5084 | dprintk("NFS: acl reply: attrlen %u > page_len %u\n", |
5089 | attrlen, page_len); | 5085 | attrlen, xdr->nwords << 2); |
5090 | return -EINVAL; | 5086 | return -EINVAL; |
5091 | } | 5087 | } |
5092 | xdr_read_pages(xdr, attrlen); | ||
5093 | res->acl_len = attrlen; | ||
5094 | } else | 5088 | } else |
5095 | status = -EOPNOTSUPP; | 5089 | status = -EOPNOTSUPP; |
5096 | 5090 | ||
diff --git a/fs/nfs/objlayout/objio_osd.c b/fs/nfs/objlayout/objio_osd.c index f50d3e8d6f2..ea6d111b03e 100644 --- a/fs/nfs/objlayout/objio_osd.c +++ b/fs/nfs/objlayout/objio_osd.c | |||
@@ -570,17 +570,66 @@ static bool objio_pg_test(struct nfs_pageio_descriptor *pgio, | |||
570 | return false; | 570 | return false; |
571 | 571 | ||
572 | return pgio->pg_count + req->wb_bytes <= | 572 | return pgio->pg_count + req->wb_bytes <= |
573 | OBJIO_LSEG(pgio->pg_lseg)->layout.max_io_length; | 573 | (unsigned long)pgio->pg_layout_private; |
574 | } | ||
575 | |||
576 | void objio_init_read(struct nfs_pageio_descriptor *pgio, struct nfs_page *req) | ||
577 | { | ||
578 | pnfs_generic_pg_init_read(pgio, req); | ||
579 | if (unlikely(pgio->pg_lseg == NULL)) | ||
580 | return; /* Not pNFS */ | ||
581 | |||
582 | pgio->pg_layout_private = (void *) | ||
583 | OBJIO_LSEG(pgio->pg_lseg)->layout.max_io_length; | ||
584 | } | ||
585 | |||
586 | static bool aligned_on_raid_stripe(u64 offset, struct ore_layout *layout, | ||
587 | unsigned long *stripe_end) | ||
588 | { | ||
589 | u32 stripe_off; | ||
590 | unsigned stripe_size; | ||
591 | |||
592 | if (layout->raid_algorithm == PNFS_OSD_RAID_0) | ||
593 | return true; | ||
594 | |||
595 | stripe_size = layout->stripe_unit * | ||
596 | (layout->group_width - layout->parity); | ||
597 | |||
598 | div_u64_rem(offset, stripe_size, &stripe_off); | ||
599 | if (!stripe_off) | ||
600 | return true; | ||
601 | |||
602 | *stripe_end = stripe_size - stripe_off; | ||
603 | return false; | ||
604 | } | ||
605 | |||
606 | void objio_init_write(struct nfs_pageio_descriptor *pgio, struct nfs_page *req) | ||
607 | { | ||
608 | unsigned long stripe_end = 0; | ||
609 | |||
610 | pnfs_generic_pg_init_write(pgio, req); | ||
611 | if (unlikely(pgio->pg_lseg == NULL)) | ||
612 | return; /* Not pNFS */ | ||
613 | |||
614 | if (req->wb_offset || | ||
615 | !aligned_on_raid_stripe(req->wb_index * PAGE_SIZE, | ||
616 | &OBJIO_LSEG(pgio->pg_lseg)->layout, | ||
617 | &stripe_end)) { | ||
618 | pgio->pg_layout_private = (void *)stripe_end; | ||
619 | } else { | ||
620 | pgio->pg_layout_private = (void *) | ||
621 | OBJIO_LSEG(pgio->pg_lseg)->layout.max_io_length; | ||
622 | } | ||
574 | } | 623 | } |
575 | 624 | ||
576 | static const struct nfs_pageio_ops objio_pg_read_ops = { | 625 | static const struct nfs_pageio_ops objio_pg_read_ops = { |
577 | .pg_init = pnfs_generic_pg_init_read, | 626 | .pg_init = objio_init_read, |
578 | .pg_test = objio_pg_test, | 627 | .pg_test = objio_pg_test, |
579 | .pg_doio = pnfs_generic_pg_readpages, | 628 | .pg_doio = pnfs_generic_pg_readpages, |
580 | }; | 629 | }; |
581 | 630 | ||
582 | static const struct nfs_pageio_ops objio_pg_write_ops = { | 631 | static const struct nfs_pageio_ops objio_pg_write_ops = { |
583 | .pg_init = pnfs_generic_pg_init_write, | 632 | .pg_init = objio_init_write, |
584 | .pg_test = objio_pg_test, | 633 | .pg_test = objio_pg_test, |
585 | .pg_doio = pnfs_generic_pg_writepages, | 634 | .pg_doio = pnfs_generic_pg_writepages, |
586 | }; | 635 | }; |
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c index 1a6732ed04a..311a79681e2 100644 --- a/fs/nfs/pagelist.c +++ b/fs/nfs/pagelist.c | |||
@@ -49,6 +49,7 @@ void nfs_pgheader_init(struct nfs_pageio_descriptor *desc, | |||
49 | hdr->io_start = req_offset(hdr->req); | 49 | hdr->io_start = req_offset(hdr->req); |
50 | hdr->good_bytes = desc->pg_count; | 50 | hdr->good_bytes = desc->pg_count; |
51 | hdr->dreq = desc->pg_dreq; | 51 | hdr->dreq = desc->pg_dreq; |
52 | hdr->layout_private = desc->pg_layout_private; | ||
52 | hdr->release = release; | 53 | hdr->release = release; |
53 | hdr->completion_ops = desc->pg_completion_ops; | 54 | hdr->completion_ops = desc->pg_completion_ops; |
54 | if (hdr->completion_ops->init_hdr) | 55 | if (hdr->completion_ops->init_hdr) |
@@ -268,6 +269,7 @@ void nfs_pageio_init(struct nfs_pageio_descriptor *desc, | |||
268 | desc->pg_error = 0; | 269 | desc->pg_error = 0; |
269 | desc->pg_lseg = NULL; | 270 | desc->pg_lseg = NULL; |
270 | desc->pg_dreq = NULL; | 271 | desc->pg_dreq = NULL; |
272 | desc->pg_layout_private = NULL; | ||
271 | } | 273 | } |
272 | EXPORT_SYMBOL_GPL(nfs_pageio_init); | 274 | EXPORT_SYMBOL_GPL(nfs_pageio_init); |
273 | 275 | ||
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index 76875bfcf19..2e00feacd4b 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c | |||
@@ -583,9 +583,6 @@ send_layoutget(struct pnfs_layout_hdr *lo, | |||
583 | struct nfs_server *server = NFS_SERVER(ino); | 583 | struct nfs_server *server = NFS_SERVER(ino); |
584 | struct nfs4_layoutget *lgp; | 584 | struct nfs4_layoutget *lgp; |
585 | struct pnfs_layout_segment *lseg = NULL; | 585 | struct pnfs_layout_segment *lseg = NULL; |
586 | struct page **pages = NULL; | ||
587 | int i; | ||
588 | u32 max_resp_sz, max_pages; | ||
589 | 586 | ||
590 | dprintk("--> %s\n", __func__); | 587 | dprintk("--> %s\n", __func__); |
591 | 588 | ||
@@ -594,20 +591,6 @@ send_layoutget(struct pnfs_layout_hdr *lo, | |||
594 | if (lgp == NULL) | 591 | if (lgp == NULL) |
595 | return NULL; | 592 | return NULL; |
596 | 593 | ||
597 | /* allocate pages for xdr post processing */ | ||
598 | max_resp_sz = server->nfs_client->cl_session->fc_attrs.max_resp_sz; | ||
599 | max_pages = nfs_page_array_len(0, max_resp_sz); | ||
600 | |||
601 | pages = kcalloc(max_pages, sizeof(struct page *), gfp_flags); | ||
602 | if (!pages) | ||
603 | goto out_err_free; | ||
604 | |||
605 | for (i = 0; i < max_pages; i++) { | ||
606 | pages[i] = alloc_page(gfp_flags); | ||
607 | if (!pages[i]) | ||
608 | goto out_err_free; | ||
609 | } | ||
610 | |||
611 | lgp->args.minlength = PAGE_CACHE_SIZE; | 594 | lgp->args.minlength = PAGE_CACHE_SIZE; |
612 | if (lgp->args.minlength > range->length) | 595 | if (lgp->args.minlength > range->length) |
613 | lgp->args.minlength = range->length; | 596 | lgp->args.minlength = range->length; |
@@ -616,39 +599,19 @@ send_layoutget(struct pnfs_layout_hdr *lo, | |||
616 | lgp->args.type = server->pnfs_curr_ld->id; | 599 | lgp->args.type = server->pnfs_curr_ld->id; |
617 | lgp->args.inode = ino; | 600 | lgp->args.inode = ino; |
618 | lgp->args.ctx = get_nfs_open_context(ctx); | 601 | lgp->args.ctx = get_nfs_open_context(ctx); |
619 | lgp->args.layout.pages = pages; | ||
620 | lgp->args.layout.pglen = max_pages * PAGE_SIZE; | ||
621 | lgp->lsegpp = &lseg; | 602 | lgp->lsegpp = &lseg; |
622 | lgp->gfp_flags = gfp_flags; | 603 | lgp->gfp_flags = gfp_flags; |
623 | 604 | ||
624 | /* Synchronously retrieve layout information from server and | 605 | /* Synchronously retrieve layout information from server and |
625 | * store in lseg. | 606 | * store in lseg. |
626 | */ | 607 | */ |
627 | nfs4_proc_layoutget(lgp); | 608 | nfs4_proc_layoutget(lgp, gfp_flags); |
628 | if (!lseg) { | 609 | if (!lseg) { |
629 | /* remember that LAYOUTGET failed and suspend trying */ | 610 | /* remember that LAYOUTGET failed and suspend trying */ |
630 | set_bit(lo_fail_bit(range->iomode), &lo->plh_flags); | 611 | set_bit(lo_fail_bit(range->iomode), &lo->plh_flags); |
631 | } | 612 | } |
632 | 613 | ||
633 | /* free xdr pages */ | ||
634 | for (i = 0; i < max_pages; i++) | ||
635 | __free_page(pages[i]); | ||
636 | kfree(pages); | ||
637 | |||
638 | return lseg; | 614 | return lseg; |
639 | |||
640 | out_err_free: | ||
641 | /* free any allocated xdr pages, lgp as it's not used */ | ||
642 | if (pages) { | ||
643 | for (i = 0; i < max_pages; i++) { | ||
644 | if (!pages[i]) | ||
645 | break; | ||
646 | __free_page(pages[i]); | ||
647 | } | ||
648 | kfree(pages); | ||
649 | } | ||
650 | kfree(lgp); | ||
651 | return NULL; | ||
652 | } | 615 | } |
653 | 616 | ||
654 | /* | 617 | /* |
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h index 2c6c80503ba..745aa1b39e7 100644 --- a/fs/nfs/pnfs.h +++ b/fs/nfs/pnfs.h | |||
@@ -172,7 +172,7 @@ extern int nfs4_proc_getdevicelist(struct nfs_server *server, | |||
172 | struct pnfs_devicelist *devlist); | 172 | struct pnfs_devicelist *devlist); |
173 | extern int nfs4_proc_getdeviceinfo(struct nfs_server *server, | 173 | extern int nfs4_proc_getdeviceinfo(struct nfs_server *server, |
174 | struct pnfs_device *dev); | 174 | struct pnfs_device *dev); |
175 | extern int nfs4_proc_layoutget(struct nfs4_layoutget *lgp); | 175 | extern void nfs4_proc_layoutget(struct nfs4_layoutget *lgp, gfp_t gfp_flags); |
176 | extern int nfs4_proc_layoutreturn(struct nfs4_layoutreturn *lrp); | 176 | extern int nfs4_proc_layoutreturn(struct nfs4_layoutreturn *lrp); |
177 | 177 | ||
178 | /* pnfs.c */ | 178 | /* pnfs.c */ |
diff --git a/fs/nfs/super.c b/fs/nfs/super.c index ac6a3c55dce..239aff7338e 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c | |||
@@ -319,6 +319,34 @@ EXPORT_SYMBOL_GPL(nfs_sops); | |||
319 | static void nfs4_validate_mount_flags(struct nfs_parsed_mount_data *); | 319 | static void nfs4_validate_mount_flags(struct nfs_parsed_mount_data *); |
320 | static int nfs4_validate_mount_data(void *options, | 320 | static int nfs4_validate_mount_data(void *options, |
321 | struct nfs_parsed_mount_data *args, const char *dev_name); | 321 | struct nfs_parsed_mount_data *args, const char *dev_name); |
322 | |||
323 | struct file_system_type nfs4_fs_type = { | ||
324 | .owner = THIS_MODULE, | ||
325 | .name = "nfs4", | ||
326 | .mount = nfs_fs_mount, | ||
327 | .kill_sb = nfs_kill_super, | ||
328 | .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, | ||
329 | }; | ||
330 | EXPORT_SYMBOL_GPL(nfs4_fs_type); | ||
331 | |||
332 | static int __init register_nfs4_fs(void) | ||
333 | { | ||
334 | return register_filesystem(&nfs4_fs_type); | ||
335 | } | ||
336 | |||
337 | static void unregister_nfs4_fs(void) | ||
338 | { | ||
339 | unregister_filesystem(&nfs4_fs_type); | ||
340 | } | ||
341 | #else | ||
342 | static int __init register_nfs4_fs(void) | ||
343 | { | ||
344 | return 0; | ||
345 | } | ||
346 | |||
347 | static void unregister_nfs4_fs(void) | ||
348 | { | ||
349 | } | ||
322 | #endif | 350 | #endif |
323 | 351 | ||
324 | static struct shrinker acl_shrinker = { | 352 | static struct shrinker acl_shrinker = { |
@@ -337,12 +365,18 @@ int __init register_nfs_fs(void) | |||
337 | if (ret < 0) | 365 | if (ret < 0) |
338 | goto error_0; | 366 | goto error_0; |
339 | 367 | ||
340 | ret = nfs_register_sysctl(); | 368 | ret = register_nfs4_fs(); |
341 | if (ret < 0) | 369 | if (ret < 0) |
342 | goto error_1; | 370 | goto error_1; |
371 | |||
372 | ret = nfs_register_sysctl(); | ||
373 | if (ret < 0) | ||
374 | goto error_2; | ||
343 | register_shrinker(&acl_shrinker); | 375 | register_shrinker(&acl_shrinker); |
344 | return 0; | 376 | return 0; |
345 | 377 | ||
378 | error_2: | ||
379 | unregister_nfs4_fs(); | ||
346 | error_1: | 380 | error_1: |
347 | unregister_filesystem(&nfs_fs_type); | 381 | unregister_filesystem(&nfs_fs_type); |
348 | error_0: | 382 | error_0: |
@@ -356,6 +390,7 @@ void __exit unregister_nfs_fs(void) | |||
356 | { | 390 | { |
357 | unregister_shrinker(&acl_shrinker); | 391 | unregister_shrinker(&acl_shrinker); |
358 | nfs_unregister_sysctl(); | 392 | nfs_unregister_sysctl(); |
393 | unregister_nfs4_fs(); | ||
359 | unregister_filesystem(&nfs_fs_type); | 394 | unregister_filesystem(&nfs_fs_type); |
360 | } | 395 | } |
361 | 396 | ||
@@ -2645,4 +2680,6 @@ MODULE_PARM_DESC(max_session_slots, "Maximum number of outstanding NFSv4.1 " | |||
2645 | module_param(send_implementation_id, ushort, 0644); | 2680 | module_param(send_implementation_id, ushort, 0644); |
2646 | MODULE_PARM_DESC(send_implementation_id, | 2681 | MODULE_PARM_DESC(send_implementation_id, |
2647 | "Send implementation ID with NFSv4.1 exchange_id"); | 2682 | "Send implementation ID with NFSv4.1 exchange_id"); |
2683 | MODULE_ALIAS("nfs4"); | ||
2684 | |||
2648 | #endif /* CONFIG_NFS_V4 */ | 2685 | #endif /* CONFIG_NFS_V4 */ |
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 5829d0ce7cf..e3b55372726 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -1814,19 +1814,19 @@ int __init nfs_init_writepagecache(void) | |||
1814 | nfs_wdata_mempool = mempool_create_slab_pool(MIN_POOL_WRITE, | 1814 | nfs_wdata_mempool = mempool_create_slab_pool(MIN_POOL_WRITE, |
1815 | nfs_wdata_cachep); | 1815 | nfs_wdata_cachep); |
1816 | if (nfs_wdata_mempool == NULL) | 1816 | if (nfs_wdata_mempool == NULL) |
1817 | return -ENOMEM; | 1817 | goto out_destroy_write_cache; |
1818 | 1818 | ||
1819 | nfs_cdata_cachep = kmem_cache_create("nfs_commit_data", | 1819 | nfs_cdata_cachep = kmem_cache_create("nfs_commit_data", |
1820 | sizeof(struct nfs_commit_data), | 1820 | sizeof(struct nfs_commit_data), |
1821 | 0, SLAB_HWCACHE_ALIGN, | 1821 | 0, SLAB_HWCACHE_ALIGN, |
1822 | NULL); | 1822 | NULL); |
1823 | if (nfs_cdata_cachep == NULL) | 1823 | if (nfs_cdata_cachep == NULL) |
1824 | return -ENOMEM; | 1824 | goto out_destroy_write_mempool; |
1825 | 1825 | ||
1826 | nfs_commit_mempool = mempool_create_slab_pool(MIN_POOL_COMMIT, | 1826 | nfs_commit_mempool = mempool_create_slab_pool(MIN_POOL_COMMIT, |
1827 | nfs_wdata_cachep); | 1827 | nfs_wdata_cachep); |
1828 | if (nfs_commit_mempool == NULL) | 1828 | if (nfs_commit_mempool == NULL) |
1829 | return -ENOMEM; | 1829 | goto out_destroy_commit_cache; |
1830 | 1830 | ||
1831 | /* | 1831 | /* |
1832 | * NFS congestion size, scale with available memory. | 1832 | * NFS congestion size, scale with available memory. |
@@ -1849,11 +1849,20 @@ int __init nfs_init_writepagecache(void) | |||
1849 | nfs_congestion_kb = 256*1024; | 1849 | nfs_congestion_kb = 256*1024; |
1850 | 1850 | ||
1851 | return 0; | 1851 | return 0; |
1852 | |||
1853 | out_destroy_commit_cache: | ||
1854 | kmem_cache_destroy(nfs_cdata_cachep); | ||
1855 | out_destroy_write_mempool: | ||
1856 | mempool_destroy(nfs_wdata_mempool); | ||
1857 | out_destroy_write_cache: | ||
1858 | kmem_cache_destroy(nfs_wdata_cachep); | ||
1859 | return -ENOMEM; | ||
1852 | } | 1860 | } |
1853 | 1861 | ||
1854 | void nfs_destroy_writepagecache(void) | 1862 | void nfs_destroy_writepagecache(void) |
1855 | { | 1863 | { |
1856 | mempool_destroy(nfs_commit_mempool); | 1864 | mempool_destroy(nfs_commit_mempool); |
1865 | kmem_cache_destroy(nfs_cdata_cachep); | ||
1857 | mempool_destroy(nfs_wdata_mempool); | 1866 | mempool_destroy(nfs_wdata_mempool); |
1858 | kmem_cache_destroy(nfs_wdata_cachep); | 1867 | kmem_cache_destroy(nfs_wdata_cachep); |
1859 | } | 1868 | } |
diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c index 6522cac6057..6a10812711c 100644 --- a/fs/nilfs2/super.c +++ b/fs/nilfs2/super.c | |||
@@ -676,17 +676,13 @@ static const struct super_operations nilfs_sops = { | |||
676 | .alloc_inode = nilfs_alloc_inode, | 676 | .alloc_inode = nilfs_alloc_inode, |
677 | .destroy_inode = nilfs_destroy_inode, | 677 | .destroy_inode = nilfs_destroy_inode, |
678 | .dirty_inode = nilfs_dirty_inode, | 678 | .dirty_inode = nilfs_dirty_inode, |
679 | /* .write_inode = nilfs_write_inode, */ | ||
680 | /* .drop_inode = nilfs_drop_inode, */ | ||
681 | .evict_inode = nilfs_evict_inode, | 679 | .evict_inode = nilfs_evict_inode, |
682 | .put_super = nilfs_put_super, | 680 | .put_super = nilfs_put_super, |
683 | /* .write_super = nilfs_write_super, */ | ||
684 | .sync_fs = nilfs_sync_fs, | 681 | .sync_fs = nilfs_sync_fs, |
685 | .freeze_fs = nilfs_freeze, | 682 | .freeze_fs = nilfs_freeze, |
686 | .unfreeze_fs = nilfs_unfreeze, | 683 | .unfreeze_fs = nilfs_unfreeze, |
687 | .statfs = nilfs_statfs, | 684 | .statfs = nilfs_statfs, |
688 | .remount_fs = nilfs_remount, | 685 | .remount_fs = nilfs_remount, |
689 | /* .umount_begin */ | ||
690 | .show_options = nilfs_show_options | 686 | .show_options = nilfs_show_options |
691 | }; | 687 | }; |
692 | 688 | ||
diff --git a/fs/nilfs2/the_nilfs.h b/fs/nilfs2/the_nilfs.h index 6eee4177807..be1267a34ce 100644 --- a/fs/nilfs2/the_nilfs.h +++ b/fs/nilfs2/the_nilfs.h | |||
@@ -107,8 +107,6 @@ struct the_nilfs { | |||
107 | * used for | 107 | * used for |
108 | * - loading the latest checkpoint exclusively. | 108 | * - loading the latest checkpoint exclusively. |
109 | * - allocating a new full segment. | 109 | * - allocating a new full segment. |
110 | * - protecting s_dirt in the super_block struct | ||
111 | * (see nilfs_write_super) and the following fields. | ||
112 | */ | 110 | */ |
113 | struct buffer_head *ns_sbh[2]; | 111 | struct buffer_head *ns_sbh[2]; |
114 | struct nilfs_super_block *ns_sbp[2]; | 112 | struct nilfs_super_block *ns_sbp[2]; |
@@ -717,7 +717,7 @@ cleanup_all: | |||
717 | * here, so just reset the state. | 717 | * here, so just reset the state. |
718 | */ | 718 | */ |
719 | file_reset_write(f); | 719 | file_reset_write(f); |
720 | mnt_drop_write(f->f_path.mnt); | 720 | __mnt_drop_write(f->f_path.mnt); |
721 | } | 721 | } |
722 | } | 722 | } |
723 | cleanup_file: | 723 | cleanup_file: |
@@ -852,9 +852,10 @@ static inline int build_open_flags(int flags, umode_t mode, struct open_flags *o | |||
852 | int lookup_flags = 0; | 852 | int lookup_flags = 0; |
853 | int acc_mode; | 853 | int acc_mode; |
854 | 854 | ||
855 | if (!(flags & O_CREAT)) | 855 | if (flags & O_CREAT) |
856 | mode = 0; | 856 | op->mode = (mode & S_IALLUGO) | S_IFREG; |
857 | op->mode = mode; | 857 | else |
858 | op->mode = 0; | ||
858 | 859 | ||
859 | /* Must never be set by userspace */ | 860 | /* Must never be set by userspace */ |
860 | flags &= ~FMODE_NONOTIFY; | 861 | flags &= ~FMODE_NONOTIFY; |
diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c index 36a29b753c7..c495a3055e2 100644 --- a/fs/quota/dquot.c +++ b/fs/quota/dquot.c | |||
@@ -1589,10 +1589,10 @@ int __dquot_alloc_space(struct inode *inode, qsize_t number, int flags) | |||
1589 | goto out; | 1589 | goto out; |
1590 | } | 1590 | } |
1591 | 1591 | ||
1592 | down_read(&sb_dqopt(inode->i_sb)->dqptr_sem); | ||
1593 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) | 1592 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) |
1594 | warn[cnt].w_type = QUOTA_NL_NOWARN; | 1593 | warn[cnt].w_type = QUOTA_NL_NOWARN; |
1595 | 1594 | ||
1595 | down_read(&sb_dqopt(inode->i_sb)->dqptr_sem); | ||
1596 | spin_lock(&dq_data_lock); | 1596 | spin_lock(&dq_data_lock); |
1597 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { | 1597 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { |
1598 | if (!dquots[cnt]) | 1598 | if (!dquots[cnt]) |
diff --git a/fs/reiserfs/bitmap.c b/fs/reiserfs/bitmap.c index 4c0c7d163d1..a98b7740a0f 100644 --- a/fs/reiserfs/bitmap.c +++ b/fs/reiserfs/bitmap.c | |||
@@ -1334,9 +1334,7 @@ struct buffer_head *reiserfs_read_bitmap_block(struct super_block *sb, | |||
1334 | else if (bitmap == 0) | 1334 | else if (bitmap == 0) |
1335 | block = (REISERFS_DISK_OFFSET_IN_BYTES >> sb->s_blocksize_bits) + 1; | 1335 | block = (REISERFS_DISK_OFFSET_IN_BYTES >> sb->s_blocksize_bits) + 1; |
1336 | 1336 | ||
1337 | reiserfs_write_unlock(sb); | ||
1338 | bh = sb_bread(sb, block); | 1337 | bh = sb_bread(sb, block); |
1339 | reiserfs_write_lock(sb); | ||
1340 | if (bh == NULL) | 1338 | if (bh == NULL) |
1341 | reiserfs_warning(sb, "sh-2029: %s: bitmap block (#%u) " | 1339 | reiserfs_warning(sb, "sh-2029: %s: bitmap block (#%u) " |
1342 | "reading failed", __func__, block); | 1340 | "reading failed", __func__, block); |
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c index a6d4268fb6c..855da58db14 100644 --- a/fs/reiserfs/inode.c +++ b/fs/reiserfs/inode.c | |||
@@ -76,10 +76,10 @@ void reiserfs_evict_inode(struct inode *inode) | |||
76 | ; | 76 | ; |
77 | } | 77 | } |
78 | out: | 78 | out: |
79 | reiserfs_write_unlock_once(inode->i_sb, depth); | ||
79 | clear_inode(inode); /* note this must go after the journal_end to prevent deadlock */ | 80 | clear_inode(inode); /* note this must go after the journal_end to prevent deadlock */ |
80 | dquot_drop(inode); | 81 | dquot_drop(inode); |
81 | inode->i_blocks = 0; | 82 | inode->i_blocks = 0; |
82 | reiserfs_write_unlock_once(inode->i_sb, depth); | ||
83 | return; | 83 | return; |
84 | 84 | ||
85 | no_delete: | 85 | no_delete: |
diff --git a/fs/super.c b/fs/super.c index b05cf47463d..0902cfa6a12 100644 --- a/fs/super.c +++ b/fs/super.c | |||
@@ -537,46 +537,6 @@ void drop_super(struct super_block *sb) | |||
537 | EXPORT_SYMBOL(drop_super); | 537 | EXPORT_SYMBOL(drop_super); |
538 | 538 | ||
539 | /** | 539 | /** |
540 | * sync_supers - helper for periodic superblock writeback | ||
541 | * | ||
542 | * Call the write_super method if present on all dirty superblocks in | ||
543 | * the system. This is for the periodic writeback used by most older | ||
544 | * filesystems. For data integrity superblock writeback use | ||
545 | * sync_filesystems() instead. | ||
546 | * | ||
547 | * Note: check the dirty flag before waiting, so we don't | ||
548 | * hold up the sync while mounting a device. (The newly | ||
549 | * mounted device won't need syncing.) | ||
550 | */ | ||
551 | void sync_supers(void) | ||
552 | { | ||
553 | struct super_block *sb, *p = NULL; | ||
554 | |||
555 | spin_lock(&sb_lock); | ||
556 | list_for_each_entry(sb, &super_blocks, s_list) { | ||
557 | if (hlist_unhashed(&sb->s_instances)) | ||
558 | continue; | ||
559 | if (sb->s_op->write_super && sb->s_dirt) { | ||
560 | sb->s_count++; | ||
561 | spin_unlock(&sb_lock); | ||
562 | |||
563 | down_read(&sb->s_umount); | ||
564 | if (sb->s_root && sb->s_dirt && (sb->s_flags & MS_BORN)) | ||
565 | sb->s_op->write_super(sb); | ||
566 | up_read(&sb->s_umount); | ||
567 | |||
568 | spin_lock(&sb_lock); | ||
569 | if (p) | ||
570 | __put_super(p); | ||
571 | p = sb; | ||
572 | } | ||
573 | } | ||
574 | if (p) | ||
575 | __put_super(p); | ||
576 | spin_unlock(&sb_lock); | ||
577 | } | ||
578 | |||
579 | /** | ||
580 | * iterate_supers - call function for all active superblocks | 540 | * iterate_supers - call function for all active superblocks |
581 | * @f: function to call | 541 | * @f: function to call |
582 | * @arg: argument to pass to it | 542 | * @arg: argument to pass to it |
diff --git a/fs/ubifs/debug.h b/fs/ubifs/debug.h index 8b8cc4e945f..760de723dad 100644 --- a/fs/ubifs/debug.h +++ b/fs/ubifs/debug.h | |||
@@ -167,7 +167,7 @@ struct ubifs_global_debug_info { | |||
167 | #define ubifs_dbg_msg(type, fmt, ...) \ | 167 | #define ubifs_dbg_msg(type, fmt, ...) \ |
168 | pr_debug("UBIFS DBG " type ": " fmt "\n", ##__VA_ARGS__) | 168 | pr_debug("UBIFS DBG " type ": " fmt "\n", ##__VA_ARGS__) |
169 | 169 | ||
170 | #define DBG_KEY_BUF_LEN 32 | 170 | #define DBG_KEY_BUF_LEN 48 |
171 | #define ubifs_dbg_msg_key(type, key, fmt, ...) do { \ | 171 | #define ubifs_dbg_msg_key(type, key, fmt, ...) do { \ |
172 | char __tmp_key_buf[DBG_KEY_BUF_LEN]; \ | 172 | char __tmp_key_buf[DBG_KEY_BUF_LEN]; \ |
173 | pr_debug("UBIFS DBG " type ": " fmt "%s\n", ##__VA_ARGS__, \ | 173 | pr_debug("UBIFS DBG " type ": " fmt "%s\n", ##__VA_ARGS__, \ |
diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c index 35389ca2d26..7bd6e72afd1 100644 --- a/fs/ubifs/file.c +++ b/fs/ubifs/file.c | |||
@@ -37,11 +37,11 @@ | |||
37 | * | 37 | * |
38 | * A thing to keep in mind: inode @i_mutex is locked in most VFS operations we | 38 | * A thing to keep in mind: inode @i_mutex is locked in most VFS operations we |
39 | * implement. However, this is not true for 'ubifs_writepage()', which may be | 39 | * implement. However, this is not true for 'ubifs_writepage()', which may be |
40 | * called with @i_mutex unlocked. For example, when pdflush is doing background | 40 | * called with @i_mutex unlocked. For example, when flusher thread is doing |
41 | * write-back, it calls 'ubifs_writepage()' with unlocked @i_mutex. At "normal" | 41 | * background write-back, it calls 'ubifs_writepage()' with unlocked @i_mutex. |
42 | * work-paths the @i_mutex is locked in 'ubifs_writepage()', e.g. in the | 42 | * At "normal" work-paths the @i_mutex is locked in 'ubifs_writepage()', e.g. |
43 | * "sys_write -> alloc_pages -> direct reclaim path". So, in 'ubifs_writepage()' | 43 | * in the "sys_write -> alloc_pages -> direct reclaim path". So, in |
44 | * we are only guaranteed that the page is locked. | 44 | * 'ubifs_writepage()' we are only guaranteed that the page is locked. |
45 | * | 45 | * |
46 | * Similarly, @i_mutex is not always locked in 'ubifs_readpage()', e.g., the | 46 | * Similarly, @i_mutex is not always locked in 'ubifs_readpage()', e.g., the |
47 | * read-ahead path does not lock it ("sys_read -> generic_file_aio_read -> | 47 | * read-ahead path does not lock it ("sys_read -> generic_file_aio_read -> |
diff --git a/fs/ubifs/lpt.c b/fs/ubifs/lpt.c index ce33b2beb15..8640920766e 100644 --- a/fs/ubifs/lpt.c +++ b/fs/ubifs/lpt.c | |||
@@ -1749,7 +1749,10 @@ int ubifs_lpt_init(struct ubifs_info *c, int rd, int wr) | |||
1749 | return 0; | 1749 | return 0; |
1750 | 1750 | ||
1751 | out_err: | 1751 | out_err: |
1752 | ubifs_lpt_free(c, 0); | 1752 | if (wr) |
1753 | ubifs_lpt_free(c, 1); | ||
1754 | if (rd) | ||
1755 | ubifs_lpt_free(c, 0); | ||
1753 | return err; | 1756 | return err; |
1754 | } | 1757 | } |
1755 | 1758 | ||
diff --git a/fs/ubifs/recovery.c b/fs/ubifs/recovery.c index c30d976b4be..edeec499c04 100644 --- a/fs/ubifs/recovery.c +++ b/fs/ubifs/recovery.c | |||
@@ -788,7 +788,7 @@ struct ubifs_scan_leb *ubifs_recover_leb(struct ubifs_info *c, int lnum, | |||
788 | 788 | ||
789 | corrupted_rescan: | 789 | corrupted_rescan: |
790 | /* Re-scan the corrupted data with verbose messages */ | 790 | /* Re-scan the corrupted data with verbose messages */ |
791 | ubifs_err("corruptio %d", ret); | 791 | ubifs_err("corruption %d", ret); |
792 | ubifs_scan_a_node(c, buf, len, lnum, offs, 1); | 792 | ubifs_scan_a_node(c, buf, len, lnum, offs, 1); |
793 | corrupted: | 793 | corrupted: |
794 | ubifs_scanned_corruption(c, lnum, offs, buf); | 794 | ubifs_scanned_corruption(c, lnum, offs, buf); |
diff --git a/fs/ubifs/replay.c b/fs/ubifs/replay.c index eba46d4a761..94d78fc5d4e 100644 --- a/fs/ubifs/replay.c +++ b/fs/ubifs/replay.c | |||
@@ -1026,7 +1026,6 @@ int ubifs_replay_journal(struct ubifs_info *c) | |||
1026 | c->replaying = 1; | 1026 | c->replaying = 1; |
1027 | lnum = c->ltail_lnum = c->lhead_lnum; | 1027 | lnum = c->ltail_lnum = c->lhead_lnum; |
1028 | 1028 | ||
1029 | lnum = UBIFS_LOG_LNUM; | ||
1030 | do { | 1029 | do { |
1031 | err = replay_log_leb(c, lnum, 0, c->sbuf); | 1030 | err = replay_log_leb(c, lnum, 0, c->sbuf); |
1032 | if (err == 1) | 1031 | if (err == 1) |
@@ -1035,7 +1034,7 @@ int ubifs_replay_journal(struct ubifs_info *c) | |||
1035 | if (err) | 1034 | if (err) |
1036 | goto out; | 1035 | goto out; |
1037 | lnum = ubifs_next_log_lnum(c, lnum); | 1036 | lnum = ubifs_next_log_lnum(c, lnum); |
1038 | } while (lnum != UBIFS_LOG_LNUM); | 1037 | } while (lnum != c->ltail_lnum); |
1039 | 1038 | ||
1040 | err = replay_buds(c); | 1039 | err = replay_buds(c); |
1041 | if (err) | 1040 | if (err) |
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 1c766c39c03..71a197f0f93 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c | |||
@@ -303,7 +303,7 @@ static int ubifs_write_inode(struct inode *inode, struct writeback_control *wbc) | |||
303 | mutex_lock(&ui->ui_mutex); | 303 | mutex_lock(&ui->ui_mutex); |
304 | /* | 304 | /* |
305 | * Due to races between write-back forced by budgeting | 305 | * Due to races between write-back forced by budgeting |
306 | * (see 'sync_some_inodes()') and pdflush write-back, the inode may | 306 | * (see 'sync_some_inodes()') and background write-back, the inode may |
307 | * have already been synchronized, do not do this again. This might | 307 | * have already been synchronized, do not do this again. This might |
308 | * also happen if it was synchronized in an VFS operation, e.g. | 308 | * also happen if it was synchronized in an VFS operation, e.g. |
309 | * 'ubifs_link()'. | 309 | * 'ubifs_link()'. |
@@ -1157,9 +1157,6 @@ static int check_free_space(struct ubifs_info *c) | |||
1157 | * | 1157 | * |
1158 | * This function mounts UBIFS file system. Returns zero in case of success and | 1158 | * This function mounts UBIFS file system. Returns zero in case of success and |
1159 | * a negative error code in case of failure. | 1159 | * a negative error code in case of failure. |
1160 | * | ||
1161 | * Note, the function does not de-allocate resources it it fails half way | ||
1162 | * through, and the caller has to do this instead. | ||
1163 | */ | 1160 | */ |
1164 | static int mount_ubifs(struct ubifs_info *c) | 1161 | static int mount_ubifs(struct ubifs_info *c) |
1165 | { | 1162 | { |
diff --git a/fs/udf/inode.c b/fs/udf/inode.c index fafaad795cd..aa233469b3c 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c | |||
@@ -1124,14 +1124,17 @@ int udf_setsize(struct inode *inode, loff_t newsize) | |||
1124 | if (err) | 1124 | if (err) |
1125 | return err; | 1125 | return err; |
1126 | down_write(&iinfo->i_data_sem); | 1126 | down_write(&iinfo->i_data_sem); |
1127 | } else | 1127 | } else { |
1128 | iinfo->i_lenAlloc = newsize; | 1128 | iinfo->i_lenAlloc = newsize; |
1129 | goto set_size; | ||
1130 | } | ||
1129 | } | 1131 | } |
1130 | err = udf_extend_file(inode, newsize); | 1132 | err = udf_extend_file(inode, newsize); |
1131 | if (err) { | 1133 | if (err) { |
1132 | up_write(&iinfo->i_data_sem); | 1134 | up_write(&iinfo->i_data_sem); |
1133 | return err; | 1135 | return err; |
1134 | } | 1136 | } |
1137 | set_size: | ||
1135 | truncate_setsize(inode, newsize); | 1138 | truncate_setsize(inode, newsize); |
1136 | up_write(&iinfo->i_data_sem); | 1139 | up_write(&iinfo->i_data_sem); |
1137 | } else { | 1140 | } else { |
diff --git a/fs/udf/super.c b/fs/udf/super.c index dcbf98722af..18fc038a438 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c | |||
@@ -1344,6 +1344,7 @@ static int udf_load_logicalvol(struct super_block *sb, sector_t block, | |||
1344 | udf_err(sb, "error loading logical volume descriptor: " | 1344 | udf_err(sb, "error loading logical volume descriptor: " |
1345 | "Partition table too long (%u > %lu)\n", table_len, | 1345 | "Partition table too long (%u > %lu)\n", table_len, |
1346 | sb->s_blocksize - sizeof(*lvd)); | 1346 | sb->s_blocksize - sizeof(*lvd)); |
1347 | ret = 1; | ||
1347 | goto out_bh; | 1348 | goto out_bh; |
1348 | } | 1349 | } |
1349 | 1350 | ||
@@ -1388,8 +1389,10 @@ static int udf_load_logicalvol(struct super_block *sb, sector_t block, | |||
1388 | UDF_ID_SPARABLE, | 1389 | UDF_ID_SPARABLE, |
1389 | strlen(UDF_ID_SPARABLE))) { | 1390 | strlen(UDF_ID_SPARABLE))) { |
1390 | if (udf_load_sparable_map(sb, map, | 1391 | if (udf_load_sparable_map(sb, map, |
1391 | (struct sparablePartitionMap *)gpm) < 0) | 1392 | (struct sparablePartitionMap *)gpm) < 0) { |
1393 | ret = 1; | ||
1392 | goto out_bh; | 1394 | goto out_bh; |
1395 | } | ||
1393 | } else if (!strncmp(upm2->partIdent.ident, | 1396 | } else if (!strncmp(upm2->partIdent.ident, |
1394 | UDF_ID_METADATA, | 1397 | UDF_ID_METADATA, |
1395 | strlen(UDF_ID_METADATA))) { | 1398 | strlen(UDF_ID_METADATA))) { |
@@ -2000,6 +2003,8 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent) | |||
2000 | if (!silent) | 2003 | if (!silent) |
2001 | pr_notice("Rescanning with blocksize %d\n", | 2004 | pr_notice("Rescanning with blocksize %d\n", |
2002 | UDF_DEFAULT_BLOCKSIZE); | 2005 | UDF_DEFAULT_BLOCKSIZE); |
2006 | brelse(sbi->s_lvid_bh); | ||
2007 | sbi->s_lvid_bh = NULL; | ||
2003 | uopt.blocksize = UDF_DEFAULT_BLOCKSIZE; | 2008 | uopt.blocksize = UDF_DEFAULT_BLOCKSIZE; |
2004 | ret = udf_load_vrs(sb, &uopt, silent, &fileset); | 2009 | ret = udf_load_vrs(sb, &uopt, silent, &fileset); |
2005 | } | 2010 | } |