diff options
Diffstat (limited to 'fs')
44 files changed, 851 insertions, 749 deletions
diff --git a/fs/buffer.c b/fs/buffer.c index 76403b1764c5..7249e014819e 100644 --- a/fs/buffer.c +++ b/fs/buffer.c | |||
@@ -2563,7 +2563,7 @@ int nobh_write_end(struct file *file, struct address_space *mapping, | |||
2563 | struct page *page, void *fsdata) | 2563 | struct page *page, void *fsdata) |
2564 | { | 2564 | { |
2565 | struct inode *inode = page->mapping->host; | 2565 | struct inode *inode = page->mapping->host; |
2566 | struct buffer_head *head = NULL; | 2566 | struct buffer_head *head = fsdata; |
2567 | struct buffer_head *bh; | 2567 | struct buffer_head *bh; |
2568 | 2568 | ||
2569 | if (!PageMappedToDisk(page)) { | 2569 | if (!PageMappedToDisk(page)) { |
@@ -2584,7 +2584,6 @@ int nobh_write_end(struct file *file, struct address_space *mapping, | |||
2584 | unlock_page(page); | 2584 | unlock_page(page); |
2585 | page_cache_release(page); | 2585 | page_cache_release(page); |
2586 | 2586 | ||
2587 | head = fsdata; | ||
2588 | while (head) { | 2587 | while (head) { |
2589 | bh = head; | 2588 | bh = head; |
2590 | head = head->b_this_page; | 2589 | head = head->b_this_page; |
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index 0a3ee5a322b0..5574ba3ab1f9 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h | |||
@@ -103,7 +103,7 @@ extern int cifs_ioctl(struct inode *inode, struct file *filep, | |||
103 | unsigned int command, unsigned long arg); | 103 | unsigned int command, unsigned long arg); |
104 | 104 | ||
105 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 105 | #ifdef CONFIG_CIFS_EXPERIMENTAL |
106 | extern struct export_operations cifs_export_ops; | 106 | extern const struct export_operations cifs_export_ops; |
107 | #endif /* EXPERIMENTAL */ | 107 | #endif /* EXPERIMENTAL */ |
108 | 108 | ||
109 | #define CIFS_VERSION "1.51" | 109 | #define CIFS_VERSION "1.51" |
diff --git a/fs/cifs/export.c b/fs/cifs/export.c index d614b91caeca..75949d6a5f1b 100644 --- a/fs/cifs/export.c +++ b/fs/cifs/export.c | |||
@@ -53,7 +53,7 @@ static struct dentry *cifs_get_parent(struct dentry *dentry) | |||
53 | return ERR_PTR(-EACCES); | 53 | return ERR_PTR(-EACCES); |
54 | } | 54 | } |
55 | 55 | ||
56 | struct export_operations cifs_export_ops = { | 56 | const struct export_operations cifs_export_ops = { |
57 | .get_parent = cifs_get_parent, | 57 | .get_parent = cifs_get_parent, |
58 | /* Following five export operations are unneeded so far and can default: | 58 | /* Following five export operations are unneeded so far and can default: |
59 | .get_dentry = | 59 | .get_dentry = |
diff --git a/fs/dcache.c b/fs/dcache.c index 5489b2d98a00..d9ca1e5ceb92 100644 --- a/fs/dcache.c +++ b/fs/dcache.c | |||
@@ -38,7 +38,7 @@ int sysctl_vfs_cache_pressure __read_mostly = 100; | |||
38 | EXPORT_SYMBOL_GPL(sysctl_vfs_cache_pressure); | 38 | EXPORT_SYMBOL_GPL(sysctl_vfs_cache_pressure); |
39 | 39 | ||
40 | __cacheline_aligned_in_smp DEFINE_SPINLOCK(dcache_lock); | 40 | __cacheline_aligned_in_smp DEFINE_SPINLOCK(dcache_lock); |
41 | static __cacheline_aligned_in_smp DEFINE_SEQLOCK(rename_lock); | 41 | __cacheline_aligned_in_smp DEFINE_SEQLOCK(rename_lock); |
42 | 42 | ||
43 | EXPORT_SYMBOL(dcache_lock); | 43 | EXPORT_SYMBOL(dcache_lock); |
44 | 44 | ||
@@ -1479,6 +1479,8 @@ static void switch_names(struct dentry *dentry, struct dentry *target) | |||
1479 | * dentry:internal, target:external. Steal target's | 1479 | * dentry:internal, target:external. Steal target's |
1480 | * storage and make target internal. | 1480 | * storage and make target internal. |
1481 | */ | 1481 | */ |
1482 | memcpy(target->d_iname, dentry->d_name.name, | ||
1483 | dentry->d_name.len + 1); | ||
1482 | dentry->d_name.name = target->d_name.name; | 1484 | dentry->d_name.name = target->d_name.name; |
1483 | target->d_name.name = target->d_iname; | 1485 | target->d_name.name = target->d_iname; |
1484 | } | 1486 | } |
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c index 11be8a325e26..6a713b33992f 100644 --- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c | |||
@@ -413,7 +413,7 @@ struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry, | |||
413 | d_move(old_dentry, dentry); | 413 | d_move(old_dentry, dentry); |
414 | fsnotify_move(old_dir->d_inode, new_dir->d_inode, old_name, | 414 | fsnotify_move(old_dir->d_inode, new_dir->d_inode, old_name, |
415 | old_dentry->d_name.name, S_ISDIR(old_dentry->d_inode->i_mode), | 415 | old_dentry->d_name.name, S_ISDIR(old_dentry->d_inode->i_mode), |
416 | NULL, old_dentry->d_inode); | 416 | NULL, old_dentry); |
417 | fsnotify_oldname_free(old_name); | 417 | fsnotify_oldname_free(old_name); |
418 | unlock_rename(new_dir, old_dir); | 418 | unlock_rename(new_dir, old_dir); |
419 | dput(dentry); | 419 | dput(dentry); |
diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c index 1ae90ef2c74d..0a9882edf562 100644 --- a/fs/ecryptfs/crypto.c +++ b/fs/ecryptfs/crypto.c | |||
@@ -283,7 +283,7 @@ int virt_to_scatterlist(const void *addr, int size, struct scatterlist *sg, | |||
283 | pg = virt_to_page(addr); | 283 | pg = virt_to_page(addr); |
284 | offset = offset_in_page(addr); | 284 | offset = offset_in_page(addr); |
285 | if (sg) { | 285 | if (sg) { |
286 | sg[i].page = pg; | 286 | sg_set_page(&sg[i], pg); |
287 | sg[i].offset = offset; | 287 | sg[i].offset = offset; |
288 | } | 288 | } |
289 | remainder_of_page = PAGE_CACHE_SIZE - offset; | 289 | remainder_of_page = PAGE_CACHE_SIZE - offset; |
@@ -713,10 +713,13 @@ ecryptfs_encrypt_page_offset(struct ecryptfs_crypt_stat *crypt_stat, | |||
713 | { | 713 | { |
714 | struct scatterlist src_sg, dst_sg; | 714 | struct scatterlist src_sg, dst_sg; |
715 | 715 | ||
716 | src_sg.page = src_page; | 716 | sg_init_table(&src_sg, 1); |
717 | sg_init_table(&dst_sg, 1); | ||
718 | |||
719 | sg_set_page(&src_sg, src_page); | ||
717 | src_sg.offset = src_offset; | 720 | src_sg.offset = src_offset; |
718 | src_sg.length = size; | 721 | src_sg.length = size; |
719 | dst_sg.page = dst_page; | 722 | sg_set_page(&dst_sg, dst_page); |
720 | dst_sg.offset = dst_offset; | 723 | dst_sg.offset = dst_offset; |
721 | dst_sg.length = size; | 724 | dst_sg.length = size; |
722 | return encrypt_scatterlist(crypt_stat, &dst_sg, &src_sg, size, iv); | 725 | return encrypt_scatterlist(crypt_stat, &dst_sg, &src_sg, size, iv); |
@@ -742,10 +745,13 @@ ecryptfs_decrypt_page_offset(struct ecryptfs_crypt_stat *crypt_stat, | |||
742 | { | 745 | { |
743 | struct scatterlist src_sg, dst_sg; | 746 | struct scatterlist src_sg, dst_sg; |
744 | 747 | ||
745 | src_sg.page = src_page; | 748 | sg_init_table(&src_sg, 1); |
749 | sg_init_table(&dst_sg, 1); | ||
750 | |||
751 | sg_set_page(&src_sg, src_page); | ||
746 | src_sg.offset = src_offset; | 752 | src_sg.offset = src_offset; |
747 | src_sg.length = size; | 753 | src_sg.length = size; |
748 | dst_sg.page = dst_page; | 754 | sg_set_page(&dst_sg, dst_page); |
749 | dst_sg.offset = dst_offset; | 755 | dst_sg.offset = dst_offset; |
750 | dst_sg.length = size; | 756 | dst_sg.length = size; |
751 | return decrypt_scatterlist(crypt_stat, &dst_sg, &src_sg, size, iv); | 757 | return decrypt_scatterlist(crypt_stat, &dst_sg, &src_sg, size, iv); |
diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c index 89d9710dd63d..263fed88c0ca 100644 --- a/fs/ecryptfs/keystore.c +++ b/fs/ecryptfs/keystore.c | |||
@@ -1040,6 +1040,9 @@ decrypt_passphrase_encrypted_session_key(struct ecryptfs_auth_tok *auth_tok, | |||
1040 | }; | 1040 | }; |
1041 | int rc = 0; | 1041 | int rc = 0; |
1042 | 1042 | ||
1043 | sg_init_table(&dst_sg, 1); | ||
1044 | sg_init_table(&src_sg, 1); | ||
1045 | |||
1043 | if (unlikely(ecryptfs_verbosity > 0)) { | 1046 | if (unlikely(ecryptfs_verbosity > 0)) { |
1044 | ecryptfs_printk( | 1047 | ecryptfs_printk( |
1045 | KERN_DEBUG, "Session key encryption key (size [%d]):\n", | 1048 | KERN_DEBUG, "Session key encryption key (size [%d]):\n", |
diff --git a/fs/efs/namei.c b/fs/efs/namei.c index 5276b19423c1..f7f407075be1 100644 --- a/fs/efs/namei.c +++ b/fs/efs/namei.c | |||
@@ -10,6 +10,8 @@ | |||
10 | #include <linux/string.h> | 10 | #include <linux/string.h> |
11 | #include <linux/efs_fs.h> | 11 | #include <linux/efs_fs.h> |
12 | #include <linux/smp_lock.h> | 12 | #include <linux/smp_lock.h> |
13 | #include <linux/exportfs.h> | ||
14 | |||
13 | 15 | ||
14 | static efs_ino_t efs_find_entry(struct inode *inode, const char *name, int len) { | 16 | static efs_ino_t efs_find_entry(struct inode *inode, const char *name, int len) { |
15 | struct buffer_head *bh; | 17 | struct buffer_head *bh; |
@@ -75,13 +77,10 @@ struct dentry *efs_lookup(struct inode *dir, struct dentry *dentry, struct namei | |||
75 | return NULL; | 77 | return NULL; |
76 | } | 78 | } |
77 | 79 | ||
78 | struct dentry *efs_get_dentry(struct super_block *sb, void *vobjp) | 80 | static struct inode *efs_nfs_get_inode(struct super_block *sb, u64 ino, |
81 | u32 generation) | ||
79 | { | 82 | { |
80 | __u32 *objp = vobjp; | ||
81 | unsigned long ino = objp[0]; | ||
82 | __u32 generation = objp[1]; | ||
83 | struct inode *inode; | 83 | struct inode *inode; |
84 | struct dentry *result; | ||
85 | 84 | ||
86 | if (ino == 0) | 85 | if (ino == 0) |
87 | return ERR_PTR(-ESTALE); | 86 | return ERR_PTR(-ESTALE); |
@@ -91,20 +90,25 @@ struct dentry *efs_get_dentry(struct super_block *sb, void *vobjp) | |||
91 | 90 | ||
92 | if (is_bad_inode(inode) || | 91 | if (is_bad_inode(inode) || |
93 | (generation && inode->i_generation != generation)) { | 92 | (generation && inode->i_generation != generation)) { |
94 | result = ERR_PTR(-ESTALE); | 93 | iput(inode); |
95 | goto out_iput; | 94 | return ERR_PTR(-ESTALE); |
96 | } | 95 | } |
97 | 96 | ||
98 | result = d_alloc_anon(inode); | 97 | return inode; |
99 | if (!result) { | 98 | } |
100 | result = ERR_PTR(-ENOMEM); | ||
101 | goto out_iput; | ||
102 | } | ||
103 | return result; | ||
104 | 99 | ||
105 | out_iput: | 100 | struct dentry *efs_fh_to_dentry(struct super_block *sb, struct fid *fid, |
106 | iput(inode); | 101 | int fh_len, int fh_type) |
107 | return result; | 102 | { |
103 | return generic_fh_to_dentry(sb, fid, fh_len, fh_type, | ||
104 | efs_nfs_get_inode); | ||
105 | } | ||
106 | |||
107 | struct dentry *efs_fh_to_parent(struct super_block *sb, struct fid *fid, | ||
108 | int fh_len, int fh_type) | ||
109 | { | ||
110 | return generic_fh_to_parent(sb, fid, fh_len, fh_type, | ||
111 | efs_nfs_get_inode); | ||
108 | } | 112 | } |
109 | 113 | ||
110 | struct dentry *efs_get_parent(struct dentry *child) | 114 | struct dentry *efs_get_parent(struct dentry *child) |
diff --git a/fs/efs/super.c b/fs/efs/super.c index 25d0326c5f1c..c79bc627f107 100644 --- a/fs/efs/super.c +++ b/fs/efs/super.c | |||
@@ -113,8 +113,9 @@ static const struct super_operations efs_superblock_operations = { | |||
113 | .remount_fs = efs_remount, | 113 | .remount_fs = efs_remount, |
114 | }; | 114 | }; |
115 | 115 | ||
116 | static struct export_operations efs_export_ops = { | 116 | static const struct export_operations efs_export_ops = { |
117 | .get_dentry = efs_get_dentry, | 117 | .fh_to_dentry = efs_fh_to_dentry, |
118 | .fh_to_parent = efs_fh_to_parent, | ||
118 | .get_parent = efs_get_parent, | 119 | .get_parent = efs_get_parent, |
119 | }; | 120 | }; |
120 | 121 | ||
diff --git a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c index 8adb32a9387a..109ab5e44eca 100644 --- a/fs/exportfs/expfs.c +++ b/fs/exportfs/expfs.c | |||
@@ -1,4 +1,13 @@ | |||
1 | 1 | /* | |
2 | * Copyright (C) Neil Brown 2002 | ||
3 | * Copyright (C) Christoph Hellwig 2007 | ||
4 | * | ||
5 | * This file contains the code mapping from inodes to NFS file handles, | ||
6 | * and for mapping back from file handles to dentries. | ||
7 | * | ||
8 | * For details on why we do all the strange and hairy things in here | ||
9 | * take a look at Documentation/filesystems/Exporting. | ||
10 | */ | ||
2 | #include <linux/exportfs.h> | 11 | #include <linux/exportfs.h> |
3 | #include <linux/fs.h> | 12 | #include <linux/fs.h> |
4 | #include <linux/file.h> | 13 | #include <linux/file.h> |
@@ -9,32 +18,19 @@ | |||
9 | #define dprintk(fmt, args...) do{}while(0) | 18 | #define dprintk(fmt, args...) do{}while(0) |
10 | 19 | ||
11 | 20 | ||
12 | static int get_name(struct dentry *dentry, char *name, | 21 | static int get_name(struct vfsmount *mnt, struct dentry *dentry, char *name, |
13 | struct dentry *child); | 22 | struct dentry *child); |
14 | 23 | ||
15 | 24 | ||
16 | static struct dentry *exportfs_get_dentry(struct super_block *sb, void *obj) | 25 | static int exportfs_get_name(struct vfsmount *mnt, struct dentry *dir, |
26 | char *name, struct dentry *child) | ||
17 | { | 27 | { |
18 | struct dentry *result = ERR_PTR(-ESTALE); | 28 | const struct export_operations *nop = dir->d_sb->s_export_op; |
19 | |||
20 | if (sb->s_export_op->get_dentry) { | ||
21 | result = sb->s_export_op->get_dentry(sb, obj); | ||
22 | if (!result) | ||
23 | result = ERR_PTR(-ESTALE); | ||
24 | } | ||
25 | |||
26 | return result; | ||
27 | } | ||
28 | |||
29 | static int exportfs_get_name(struct dentry *dir, char *name, | ||
30 | struct dentry *child) | ||
31 | { | ||
32 | struct export_operations *nop = dir->d_sb->s_export_op; | ||
33 | 29 | ||
34 | if (nop->get_name) | 30 | if (nop->get_name) |
35 | return nop->get_name(dir, name, child); | 31 | return nop->get_name(dir, name, child); |
36 | else | 32 | else |
37 | return get_name(dir, name, child); | 33 | return get_name(mnt, dir, name, child); |
38 | } | 34 | } |
39 | 35 | ||
40 | /* | 36 | /* |
@@ -98,7 +94,7 @@ find_disconnected_root(struct dentry *dentry) | |||
98 | * It may already be, as the flag isn't always updated when connection happens. | 94 | * It may already be, as the flag isn't always updated when connection happens. |
99 | */ | 95 | */ |
100 | static int | 96 | static int |
101 | reconnect_path(struct super_block *sb, struct dentry *target_dir) | 97 | reconnect_path(struct vfsmount *mnt, struct dentry *target_dir) |
102 | { | 98 | { |
103 | char nbuf[NAME_MAX+1]; | 99 | char nbuf[NAME_MAX+1]; |
104 | int noprogress = 0; | 100 | int noprogress = 0; |
@@ -121,7 +117,7 @@ reconnect_path(struct super_block *sb, struct dentry *target_dir) | |||
121 | pd->d_flags &= ~DCACHE_DISCONNECTED; | 117 | pd->d_flags &= ~DCACHE_DISCONNECTED; |
122 | spin_unlock(&pd->d_lock); | 118 | spin_unlock(&pd->d_lock); |
123 | noprogress = 0; | 119 | noprogress = 0; |
124 | } else if (pd == sb->s_root) { | 120 | } else if (pd == mnt->mnt_sb->s_root) { |
125 | printk(KERN_ERR "export: Eeek filesystem root is not connected, impossible\n"); | 121 | printk(KERN_ERR "export: Eeek filesystem root is not connected, impossible\n"); |
126 | spin_lock(&pd->d_lock); | 122 | spin_lock(&pd->d_lock); |
127 | pd->d_flags &= ~DCACHE_DISCONNECTED; | 123 | pd->d_flags &= ~DCACHE_DISCONNECTED; |
@@ -147,8 +143,8 @@ reconnect_path(struct super_block *sb, struct dentry *target_dir) | |||
147 | struct dentry *npd; | 143 | struct dentry *npd; |
148 | 144 | ||
149 | mutex_lock(&pd->d_inode->i_mutex); | 145 | mutex_lock(&pd->d_inode->i_mutex); |
150 | if (sb->s_export_op->get_parent) | 146 | if (mnt->mnt_sb->s_export_op->get_parent) |
151 | ppd = sb->s_export_op->get_parent(pd); | 147 | ppd = mnt->mnt_sb->s_export_op->get_parent(pd); |
152 | mutex_unlock(&pd->d_inode->i_mutex); | 148 | mutex_unlock(&pd->d_inode->i_mutex); |
153 | 149 | ||
154 | if (IS_ERR(ppd)) { | 150 | if (IS_ERR(ppd)) { |
@@ -161,7 +157,7 @@ reconnect_path(struct super_block *sb, struct dentry *target_dir) | |||
161 | 157 | ||
162 | dprintk("%s: find name of %lu in %lu\n", __FUNCTION__, | 158 | dprintk("%s: find name of %lu in %lu\n", __FUNCTION__, |
163 | pd->d_inode->i_ino, ppd->d_inode->i_ino); | 159 | pd->d_inode->i_ino, ppd->d_inode->i_ino); |
164 | err = exportfs_get_name(ppd, nbuf, pd); | 160 | err = exportfs_get_name(mnt, ppd, nbuf, pd); |
165 | if (err) { | 161 | if (err) { |
166 | dput(ppd); | 162 | dput(ppd); |
167 | dput(pd); | 163 | dput(pd); |
@@ -214,125 +210,6 @@ reconnect_path(struct super_block *sb, struct dentry *target_dir) | |||
214 | return 0; | 210 | return 0; |
215 | } | 211 | } |
216 | 212 | ||
217 | /** | ||
218 | * find_exported_dentry - helper routine to implement export_operations->decode_fh | ||
219 | * @sb: The &super_block identifying the filesystem | ||
220 | * @obj: An opaque identifier of the object to be found - passed to | ||
221 | * get_inode | ||
222 | * @parent: An optional opqaue identifier of the parent of the object. | ||
223 | * @acceptable: A function used to test possible &dentries to see if they are | ||
224 | * acceptable | ||
225 | * @context: A parameter to @acceptable so that it knows on what basis to | ||
226 | * judge. | ||
227 | * | ||
228 | * find_exported_dentry is the central helper routine to enable file systems | ||
229 | * to provide the decode_fh() export_operation. It's main task is to take | ||
230 | * an &inode, find or create an appropriate &dentry structure, and possibly | ||
231 | * splice this into the dcache in the correct place. | ||
232 | * | ||
233 | * The decode_fh() operation provided by the filesystem should call | ||
234 | * find_exported_dentry() with the same parameters that it received except | ||
235 | * that instead of the file handle fragment, pointers to opaque identifiers | ||
236 | * for the object and optionally its parent are passed. The default decode_fh | ||
237 | * routine passes one pointer to the start of the filehandle fragment, and | ||
238 | * one 8 bytes into the fragment. It is expected that most filesystems will | ||
239 | * take this approach, though the offset to the parent identifier may well be | ||
240 | * different. | ||
241 | * | ||
242 | * find_exported_dentry() will call get_dentry to get an dentry pointer from | ||
243 | * the file system. If any &dentry in the d_alias list is acceptable, it will | ||
244 | * be returned. Otherwise find_exported_dentry() will attempt to splice a new | ||
245 | * &dentry into the dcache using get_name() and get_parent() to find the | ||
246 | * appropriate place. | ||
247 | */ | ||
248 | |||
249 | struct dentry * | ||
250 | find_exported_dentry(struct super_block *sb, void *obj, void *parent, | ||
251 | int (*acceptable)(void *context, struct dentry *de), | ||
252 | void *context) | ||
253 | { | ||
254 | struct dentry *result, *alias; | ||
255 | int err = -ESTALE; | ||
256 | |||
257 | /* | ||
258 | * Attempt to find the inode. | ||
259 | */ | ||
260 | result = exportfs_get_dentry(sb, obj); | ||
261 | if (IS_ERR(result)) | ||
262 | return result; | ||
263 | |||
264 | if (S_ISDIR(result->d_inode->i_mode)) { | ||
265 | if (!(result->d_flags & DCACHE_DISCONNECTED)) { | ||
266 | if (acceptable(context, result)) | ||
267 | return result; | ||
268 | err = -EACCES; | ||
269 | goto err_result; | ||
270 | } | ||
271 | |||
272 | err = reconnect_path(sb, result); | ||
273 | if (err) | ||
274 | goto err_result; | ||
275 | } else { | ||
276 | struct dentry *target_dir, *nresult; | ||
277 | char nbuf[NAME_MAX+1]; | ||
278 | |||
279 | alias = find_acceptable_alias(result, acceptable, context); | ||
280 | if (alias) | ||
281 | return alias; | ||
282 | |||
283 | if (parent == NULL) | ||
284 | goto err_result; | ||
285 | |||
286 | target_dir = exportfs_get_dentry(sb,parent); | ||
287 | if (IS_ERR(target_dir)) { | ||
288 | err = PTR_ERR(target_dir); | ||
289 | goto err_result; | ||
290 | } | ||
291 | |||
292 | err = reconnect_path(sb, target_dir); | ||
293 | if (err) { | ||
294 | dput(target_dir); | ||
295 | goto err_result; | ||
296 | } | ||
297 | |||
298 | /* | ||
299 | * As we weren't after a directory, have one more step to go. | ||
300 | */ | ||
301 | err = exportfs_get_name(target_dir, nbuf, result); | ||
302 | if (!err) { | ||
303 | mutex_lock(&target_dir->d_inode->i_mutex); | ||
304 | nresult = lookup_one_len(nbuf, target_dir, | ||
305 | strlen(nbuf)); | ||
306 | mutex_unlock(&target_dir->d_inode->i_mutex); | ||
307 | if (!IS_ERR(nresult)) { | ||
308 | if (nresult->d_inode) { | ||
309 | dput(result); | ||
310 | result = nresult; | ||
311 | } else | ||
312 | dput(nresult); | ||
313 | } | ||
314 | } | ||
315 | dput(target_dir); | ||
316 | } | ||
317 | |||
318 | alias = find_acceptable_alias(result, acceptable, context); | ||
319 | if (alias) | ||
320 | return alias; | ||
321 | |||
322 | /* drat - I just cannot find anything acceptable */ | ||
323 | dput(result); | ||
324 | /* It might be justifiable to return ESTALE here, | ||
325 | * but the filehandle at-least looks reasonable good | ||
326 | * and it may just be a permission problem, so returning | ||
327 | * -EACCESS is safer | ||
328 | */ | ||
329 | return ERR_PTR(-EACCES); | ||
330 | |||
331 | err_result: | ||
332 | dput(result); | ||
333 | return ERR_PTR(err); | ||
334 | } | ||
335 | |||
336 | struct getdents_callback { | 213 | struct getdents_callback { |
337 | char *name; /* name that was found. It already points to a | 214 | char *name; /* name that was found. It already points to a |
338 | buffer NAME_MAX+1 is size */ | 215 | buffer NAME_MAX+1 is size */ |
@@ -370,8 +247,8 @@ static int filldir_one(void * __buf, const char * name, int len, | |||
370 | * calls readdir on the parent until it finds an entry with | 247 | * calls readdir on the parent until it finds an entry with |
371 | * the same inode number as the child, and returns that. | 248 | * the same inode number as the child, and returns that. |
372 | */ | 249 | */ |
373 | static int get_name(struct dentry *dentry, char *name, | 250 | static int get_name(struct vfsmount *mnt, struct dentry *dentry, |
374 | struct dentry *child) | 251 | char *name, struct dentry *child) |
375 | { | 252 | { |
376 | struct inode *dir = dentry->d_inode; | 253 | struct inode *dir = dentry->d_inode; |
377 | int error; | 254 | int error; |
@@ -387,7 +264,7 @@ static int get_name(struct dentry *dentry, char *name, | |||
387 | /* | 264 | /* |
388 | * Open the directory ... | 265 | * Open the directory ... |
389 | */ | 266 | */ |
390 | file = dentry_open(dget(dentry), NULL, O_RDONLY); | 267 | file = dentry_open(dget(dentry), mntget(mnt), O_RDONLY); |
391 | error = PTR_ERR(file); | 268 | error = PTR_ERR(file); |
392 | if (IS_ERR(file)) | 269 | if (IS_ERR(file)) |
393 | goto out; | 270 | goto out; |
@@ -434,100 +311,177 @@ out: | |||
434 | * can be used to check that it is still valid. It places them in the | 311 | * can be used to check that it is still valid. It places them in the |
435 | * filehandle fragment where export_decode_fh expects to find them. | 312 | * filehandle fragment where export_decode_fh expects to find them. |
436 | */ | 313 | */ |
437 | static int export_encode_fh(struct dentry *dentry, __u32 *fh, int *max_len, | 314 | static int export_encode_fh(struct dentry *dentry, struct fid *fid, |
438 | int connectable) | 315 | int *max_len, int connectable) |
439 | { | 316 | { |
440 | struct inode * inode = dentry->d_inode; | 317 | struct inode * inode = dentry->d_inode; |
441 | int len = *max_len; | 318 | int len = *max_len; |
442 | int type = 1; | 319 | int type = FILEID_INO32_GEN; |
443 | 320 | ||
444 | if (len < 2 || (connectable && len < 4)) | 321 | if (len < 2 || (connectable && len < 4)) |
445 | return 255; | 322 | return 255; |
446 | 323 | ||
447 | len = 2; | 324 | len = 2; |
448 | fh[0] = inode->i_ino; | 325 | fid->i32.ino = inode->i_ino; |
449 | fh[1] = inode->i_generation; | 326 | fid->i32.gen = inode->i_generation; |
450 | if (connectable && !S_ISDIR(inode->i_mode)) { | 327 | if (connectable && !S_ISDIR(inode->i_mode)) { |
451 | struct inode *parent; | 328 | struct inode *parent; |
452 | 329 | ||
453 | spin_lock(&dentry->d_lock); | 330 | spin_lock(&dentry->d_lock); |
454 | parent = dentry->d_parent->d_inode; | 331 | parent = dentry->d_parent->d_inode; |
455 | fh[2] = parent->i_ino; | 332 | fid->i32.parent_ino = parent->i_ino; |
456 | fh[3] = parent->i_generation; | 333 | fid->i32.parent_gen = parent->i_generation; |
457 | spin_unlock(&dentry->d_lock); | 334 | spin_unlock(&dentry->d_lock); |
458 | len = 4; | 335 | len = 4; |
459 | type = 2; | 336 | type = FILEID_INO32_GEN_PARENT; |
460 | } | 337 | } |
461 | *max_len = len; | 338 | *max_len = len; |
462 | return type; | 339 | return type; |
463 | } | 340 | } |
464 | 341 | ||
465 | 342 | int exportfs_encode_fh(struct dentry *dentry, struct fid *fid, int *max_len, | |
466 | /** | ||
467 | * export_decode_fh - default export_operations->decode_fh function | ||
468 | * @sb: The superblock | ||
469 | * @fh: pointer to the file handle fragment | ||
470 | * @fh_len: length of file handle fragment | ||
471 | * @acceptable: function for testing acceptability of dentrys | ||
472 | * @context: context for @acceptable | ||
473 | * | ||
474 | * This is the default decode_fh() function. | ||
475 | * a fileid_type of 1 indicates that the filehandlefragment | ||
476 | * just contains an object identifier understood by get_dentry. | ||
477 | * a fileid_type of 2 says that there is also a directory | ||
478 | * identifier 8 bytes in to the filehandlefragement. | ||
479 | */ | ||
480 | static struct dentry *export_decode_fh(struct super_block *sb, __u32 *fh, int fh_len, | ||
481 | int fileid_type, | ||
482 | int (*acceptable)(void *context, struct dentry *de), | ||
483 | void *context) | ||
484 | { | ||
485 | __u32 parent[2]; | ||
486 | parent[0] = parent[1] = 0; | ||
487 | if (fh_len < 2 || fileid_type > 2) | ||
488 | return NULL; | ||
489 | if (fileid_type == 2) { | ||
490 | if (fh_len > 2) parent[0] = fh[2]; | ||
491 | if (fh_len > 3) parent[1] = fh[3]; | ||
492 | } | ||
493 | return find_exported_dentry(sb, fh, parent, | ||
494 | acceptable, context); | ||
495 | } | ||
496 | |||
497 | int exportfs_encode_fh(struct dentry *dentry, __u32 *fh, int *max_len, | ||
498 | int connectable) | 343 | int connectable) |
499 | { | 344 | { |
500 | struct export_operations *nop = dentry->d_sb->s_export_op; | 345 | const struct export_operations *nop = dentry->d_sb->s_export_op; |
501 | int error; | 346 | int error; |
502 | 347 | ||
503 | if (nop->encode_fh) | 348 | if (nop->encode_fh) |
504 | error = nop->encode_fh(dentry, fh, max_len, connectable); | 349 | error = nop->encode_fh(dentry, fid->raw, max_len, connectable); |
505 | else | 350 | else |
506 | error = export_encode_fh(dentry, fh, max_len, connectable); | 351 | error = export_encode_fh(dentry, fid, max_len, connectable); |
507 | 352 | ||
508 | return error; | 353 | return error; |
509 | } | 354 | } |
510 | EXPORT_SYMBOL_GPL(exportfs_encode_fh); | 355 | EXPORT_SYMBOL_GPL(exportfs_encode_fh); |
511 | 356 | ||
512 | struct dentry *exportfs_decode_fh(struct vfsmount *mnt, __u32 *fh, int fh_len, | 357 | struct dentry *exportfs_decode_fh(struct vfsmount *mnt, struct fid *fid, |
513 | int fileid_type, int (*acceptable)(void *, struct dentry *), | 358 | int fh_len, int fileid_type, |
514 | void *context) | 359 | int (*acceptable)(void *, struct dentry *), void *context) |
515 | { | 360 | { |
516 | struct export_operations *nop = mnt->mnt_sb->s_export_op; | 361 | const struct export_operations *nop = mnt->mnt_sb->s_export_op; |
517 | struct dentry *result; | 362 | struct dentry *result, *alias; |
363 | int err; | ||
518 | 364 | ||
519 | if (nop->decode_fh) { | 365 | /* |
520 | result = nop->decode_fh(mnt->mnt_sb, fh, fh_len, fileid_type, | 366 | * Try to get any dentry for the given file handle from the filesystem. |
521 | acceptable, context); | 367 | */ |
368 | result = nop->fh_to_dentry(mnt->mnt_sb, fid, fh_len, fileid_type); | ||
369 | if (!result) | ||
370 | result = ERR_PTR(-ESTALE); | ||
371 | if (IS_ERR(result)) | ||
372 | return result; | ||
373 | |||
374 | if (S_ISDIR(result->d_inode->i_mode)) { | ||
375 | /* | ||
376 | * This request is for a directory. | ||
377 | * | ||
378 | * On the positive side there is only one dentry for each | ||
379 | * directory inode. On the negative side this implies that we | ||
380 | * to ensure our dentry is connected all the way up to the | ||
381 | * filesystem root. | ||
382 | */ | ||
383 | if (result->d_flags & DCACHE_DISCONNECTED) { | ||
384 | err = reconnect_path(mnt, result); | ||
385 | if (err) | ||
386 | goto err_result; | ||
387 | } | ||
388 | |||
389 | if (!acceptable(context, result)) { | ||
390 | err = -EACCES; | ||
391 | goto err_result; | ||
392 | } | ||
393 | |||
394 | return result; | ||
522 | } else { | 395 | } else { |
523 | result = export_decode_fh(mnt->mnt_sb, fh, fh_len, fileid_type, | 396 | /* |
524 | acceptable, context); | 397 | * It's not a directory. Life is a little more complicated. |
398 | */ | ||
399 | struct dentry *target_dir, *nresult; | ||
400 | char nbuf[NAME_MAX+1]; | ||
401 | |||
402 | /* | ||
403 | * See if either the dentry we just got from the filesystem | ||
404 | * or any alias for it is acceptable. This is always true | ||
405 | * if this filesystem is exported without the subtreecheck | ||
406 | * option. If the filesystem is exported with the subtree | ||
407 | * check option there's a fair chance we need to look at | ||
408 | * the parent directory in the file handle and make sure | ||
409 | * it's connected to the filesystem root. | ||
410 | */ | ||
411 | alias = find_acceptable_alias(result, acceptable, context); | ||
412 | if (alias) | ||
413 | return alias; | ||
414 | |||
415 | /* | ||
416 | * Try to extract a dentry for the parent directory from the | ||
417 | * file handle. If this fails we'll have to give up. | ||
418 | */ | ||
419 | err = -ESTALE; | ||
420 | if (!nop->fh_to_parent) | ||
421 | goto err_result; | ||
422 | |||
423 | target_dir = nop->fh_to_parent(mnt->mnt_sb, fid, | ||
424 | fh_len, fileid_type); | ||
425 | if (!target_dir) | ||
426 | goto err_result; | ||
427 | err = PTR_ERR(target_dir); | ||
428 | if (IS_ERR(target_dir)) | ||
429 | goto err_result; | ||
430 | |||
431 | /* | ||
432 | * And as usual we need to make sure the parent directory is | ||
433 | * connected to the filesystem root. The VFS really doesn't | ||
434 | * like disconnected directories.. | ||
435 | */ | ||
436 | err = reconnect_path(mnt, target_dir); | ||
437 | if (err) { | ||
438 | dput(target_dir); | ||
439 | goto err_result; | ||
440 | } | ||
441 | |||
442 | /* | ||
443 | * Now that we've got both a well-connected parent and a | ||
444 | * dentry for the inode we're after, make sure that our | ||
445 | * inode is actually connected to the parent. | ||
446 | */ | ||
447 | err = exportfs_get_name(mnt, target_dir, nbuf, result); | ||
448 | if (!err) { | ||
449 | mutex_lock(&target_dir->d_inode->i_mutex); | ||
450 | nresult = lookup_one_len(nbuf, target_dir, | ||
451 | strlen(nbuf)); | ||
452 | mutex_unlock(&target_dir->d_inode->i_mutex); | ||
453 | if (!IS_ERR(nresult)) { | ||
454 | if (nresult->d_inode) { | ||
455 | dput(result); | ||
456 | result = nresult; | ||
457 | } else | ||
458 | dput(nresult); | ||
459 | } | ||
460 | } | ||
461 | |||
462 | /* | ||
463 | * At this point we are done with the parent, but it's pinned | ||
464 | * by the child dentry anyway. | ||
465 | */ | ||
466 | dput(target_dir); | ||
467 | |||
468 | /* | ||
469 | * And finally make sure the dentry is actually acceptable | ||
470 | * to NFSD. | ||
471 | */ | ||
472 | alias = find_acceptable_alias(result, acceptable, context); | ||
473 | if (!alias) { | ||
474 | err = -EACCES; | ||
475 | goto err_result; | ||
476 | } | ||
477 | |||
478 | return alias; | ||
525 | } | 479 | } |
526 | 480 | ||
527 | return result; | 481 | err_result: |
482 | dput(result); | ||
483 | return ERR_PTR(err); | ||
528 | } | 484 | } |
529 | EXPORT_SYMBOL_GPL(exportfs_decode_fh); | 485 | EXPORT_SYMBOL_GPL(exportfs_decode_fh); |
530 | 486 | ||
531 | EXPORT_SYMBOL(find_exported_dentry); | ||
532 | |||
533 | MODULE_LICENSE("GPL"); | 487 | MODULE_LICENSE("GPL"); |
diff --git a/fs/ext2/dir.c b/fs/ext2/dir.c index 05d9342bb64e..d868e26c15eb 100644 --- a/fs/ext2/dir.c +++ b/fs/ext2/dir.c | |||
@@ -28,6 +28,24 @@ | |||
28 | 28 | ||
29 | typedef struct ext2_dir_entry_2 ext2_dirent; | 29 | typedef struct ext2_dir_entry_2 ext2_dirent; |
30 | 30 | ||
31 | static inline unsigned ext2_rec_len_from_disk(__le16 dlen) | ||
32 | { | ||
33 | unsigned len = le16_to_cpu(dlen); | ||
34 | |||
35 | if (len == EXT2_MAX_REC_LEN) | ||
36 | return 1 << 16; | ||
37 | return len; | ||
38 | } | ||
39 | |||
40 | static inline __le16 ext2_rec_len_to_disk(unsigned len) | ||
41 | { | ||
42 | if (len == (1 << 16)) | ||
43 | return cpu_to_le16(EXT2_MAX_REC_LEN); | ||
44 | else if (len > (1 << 16)) | ||
45 | BUG(); | ||
46 | return cpu_to_le16(len); | ||
47 | } | ||
48 | |||
31 | /* | 49 | /* |
32 | * ext2 uses block-sized chunks. Arguably, sector-sized ones would be | 50 | * ext2 uses block-sized chunks. Arguably, sector-sized ones would be |
33 | * more robust, but we have what we have | 51 | * more robust, but we have what we have |
@@ -106,7 +124,7 @@ static void ext2_check_page(struct page *page) | |||
106 | } | 124 | } |
107 | for (offs = 0; offs <= limit - EXT2_DIR_REC_LEN(1); offs += rec_len) { | 125 | for (offs = 0; offs <= limit - EXT2_DIR_REC_LEN(1); offs += rec_len) { |
108 | p = (ext2_dirent *)(kaddr + offs); | 126 | p = (ext2_dirent *)(kaddr + offs); |
109 | rec_len = le16_to_cpu(p->rec_len); | 127 | rec_len = ext2_rec_len_from_disk(p->rec_len); |
110 | 128 | ||
111 | if (rec_len < EXT2_DIR_REC_LEN(1)) | 129 | if (rec_len < EXT2_DIR_REC_LEN(1)) |
112 | goto Eshort; | 130 | goto Eshort; |
@@ -204,7 +222,8 @@ static inline int ext2_match (int len, const char * const name, | |||
204 | */ | 222 | */ |
205 | static inline ext2_dirent *ext2_next_entry(ext2_dirent *p) | 223 | static inline ext2_dirent *ext2_next_entry(ext2_dirent *p) |
206 | { | 224 | { |
207 | return (ext2_dirent *)((char*)p + le16_to_cpu(p->rec_len)); | 225 | return (ext2_dirent *)((char *)p + |
226 | ext2_rec_len_from_disk(p->rec_len)); | ||
208 | } | 227 | } |
209 | 228 | ||
210 | static inline unsigned | 229 | static inline unsigned |
@@ -316,7 +335,7 @@ ext2_readdir (struct file * filp, void * dirent, filldir_t filldir) | |||
316 | return 0; | 335 | return 0; |
317 | } | 336 | } |
318 | } | 337 | } |
319 | filp->f_pos += le16_to_cpu(de->rec_len); | 338 | filp->f_pos += ext2_rec_len_from_disk(de->rec_len); |
320 | } | 339 | } |
321 | ext2_put_page(page); | 340 | ext2_put_page(page); |
322 | } | 341 | } |
@@ -425,7 +444,7 @@ void ext2_set_link(struct inode *dir, struct ext2_dir_entry_2 *de, | |||
425 | { | 444 | { |
426 | loff_t pos = page_offset(page) + | 445 | loff_t pos = page_offset(page) + |
427 | (char *) de - (char *) page_address(page); | 446 | (char *) de - (char *) page_address(page); |
428 | unsigned len = le16_to_cpu(de->rec_len); | 447 | unsigned len = ext2_rec_len_from_disk(de->rec_len); |
429 | int err; | 448 | int err; |
430 | 449 | ||
431 | lock_page(page); | 450 | lock_page(page); |
@@ -482,7 +501,7 @@ int ext2_add_link (struct dentry *dentry, struct inode *inode) | |||
482 | /* We hit i_size */ | 501 | /* We hit i_size */ |
483 | name_len = 0; | 502 | name_len = 0; |
484 | rec_len = chunk_size; | 503 | rec_len = chunk_size; |
485 | de->rec_len = cpu_to_le16(chunk_size); | 504 | de->rec_len = ext2_rec_len_to_disk(chunk_size); |
486 | de->inode = 0; | 505 | de->inode = 0; |
487 | goto got_it; | 506 | goto got_it; |
488 | } | 507 | } |
@@ -496,7 +515,7 @@ int ext2_add_link (struct dentry *dentry, struct inode *inode) | |||
496 | if (ext2_match (namelen, name, de)) | 515 | if (ext2_match (namelen, name, de)) |
497 | goto out_unlock; | 516 | goto out_unlock; |
498 | name_len = EXT2_DIR_REC_LEN(de->name_len); | 517 | name_len = EXT2_DIR_REC_LEN(de->name_len); |
499 | rec_len = le16_to_cpu(de->rec_len); | 518 | rec_len = ext2_rec_len_from_disk(de->rec_len); |
500 | if (!de->inode && rec_len >= reclen) | 519 | if (!de->inode && rec_len >= reclen) |
501 | goto got_it; | 520 | goto got_it; |
502 | if (rec_len >= name_len + reclen) | 521 | if (rec_len >= name_len + reclen) |
@@ -518,8 +537,8 @@ got_it: | |||
518 | goto out_unlock; | 537 | goto out_unlock; |
519 | if (de->inode) { | 538 | if (de->inode) { |
520 | ext2_dirent *de1 = (ext2_dirent *) ((char *) de + name_len); | 539 | ext2_dirent *de1 = (ext2_dirent *) ((char *) de + name_len); |
521 | de1->rec_len = cpu_to_le16(rec_len - name_len); | 540 | de1->rec_len = ext2_rec_len_to_disk(rec_len - name_len); |
522 | de->rec_len = cpu_to_le16(name_len); | 541 | de->rec_len = ext2_rec_len_to_disk(name_len); |
523 | de = de1; | 542 | de = de1; |
524 | } | 543 | } |
525 | de->name_len = namelen; | 544 | de->name_len = namelen; |
@@ -550,7 +569,8 @@ int ext2_delete_entry (struct ext2_dir_entry_2 * dir, struct page * page ) | |||
550 | struct inode *inode = mapping->host; | 569 | struct inode *inode = mapping->host; |
551 | char *kaddr = page_address(page); | 570 | char *kaddr = page_address(page); |
552 | unsigned from = ((char*)dir - kaddr) & ~(ext2_chunk_size(inode)-1); | 571 | unsigned from = ((char*)dir - kaddr) & ~(ext2_chunk_size(inode)-1); |
553 | unsigned to = ((char*)dir - kaddr) + le16_to_cpu(dir->rec_len); | 572 | unsigned to = ((char *)dir - kaddr) + |
573 | ext2_rec_len_from_disk(dir->rec_len); | ||
554 | loff_t pos; | 574 | loff_t pos; |
555 | ext2_dirent * pde = NULL; | 575 | ext2_dirent * pde = NULL; |
556 | ext2_dirent * de = (ext2_dirent *) (kaddr + from); | 576 | ext2_dirent * de = (ext2_dirent *) (kaddr + from); |
@@ -574,7 +594,7 @@ int ext2_delete_entry (struct ext2_dir_entry_2 * dir, struct page * page ) | |||
574 | &page, NULL); | 594 | &page, NULL); |
575 | BUG_ON(err); | 595 | BUG_ON(err); |
576 | if (pde) | 596 | if (pde) |
577 | pde->rec_len = cpu_to_le16(to - from); | 597 | pde->rec_len = ext2_rec_len_to_disk(to - from); |
578 | dir->inode = 0; | 598 | dir->inode = 0; |
579 | err = ext2_commit_chunk(page, pos, to - from); | 599 | err = ext2_commit_chunk(page, pos, to - from); |
580 | inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC; | 600 | inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC; |
@@ -610,14 +630,14 @@ int ext2_make_empty(struct inode *inode, struct inode *parent) | |||
610 | memset(kaddr, 0, chunk_size); | 630 | memset(kaddr, 0, chunk_size); |
611 | de = (struct ext2_dir_entry_2 *)kaddr; | 631 | de = (struct ext2_dir_entry_2 *)kaddr; |
612 | de->name_len = 1; | 632 | de->name_len = 1; |
613 | de->rec_len = cpu_to_le16(EXT2_DIR_REC_LEN(1)); | 633 | de->rec_len = ext2_rec_len_to_disk(EXT2_DIR_REC_LEN(1)); |
614 | memcpy (de->name, ".\0\0", 4); | 634 | memcpy (de->name, ".\0\0", 4); |
615 | de->inode = cpu_to_le32(inode->i_ino); | 635 | de->inode = cpu_to_le32(inode->i_ino); |
616 | ext2_set_de_type (de, inode); | 636 | ext2_set_de_type (de, inode); |
617 | 637 | ||
618 | de = (struct ext2_dir_entry_2 *)(kaddr + EXT2_DIR_REC_LEN(1)); | 638 | de = (struct ext2_dir_entry_2 *)(kaddr + EXT2_DIR_REC_LEN(1)); |
619 | de->name_len = 2; | 639 | de->name_len = 2; |
620 | de->rec_len = cpu_to_le16(chunk_size - EXT2_DIR_REC_LEN(1)); | 640 | de->rec_len = ext2_rec_len_to_disk(chunk_size - EXT2_DIR_REC_LEN(1)); |
621 | de->inode = cpu_to_le32(parent->i_ino); | 641 | de->inode = cpu_to_le32(parent->i_ino); |
622 | memcpy (de->name, "..\0", 4); | 642 | memcpy (de->name, "..\0", 4); |
623 | ext2_set_de_type (de, inode); | 643 | ext2_set_de_type (de, inode); |
diff --git a/fs/ext2/super.c b/fs/ext2/super.c index 77bd5f9262f9..154e25f13d77 100644 --- a/fs/ext2/super.c +++ b/fs/ext2/super.c | |||
@@ -311,13 +311,10 @@ static const struct super_operations ext2_sops = { | |||
311 | #endif | 311 | #endif |
312 | }; | 312 | }; |
313 | 313 | ||
314 | static struct dentry *ext2_get_dentry(struct super_block *sb, void *vobjp) | 314 | static struct inode *ext2_nfs_get_inode(struct super_block *sb, |
315 | u64 ino, u32 generation) | ||
315 | { | 316 | { |
316 | __u32 *objp = vobjp; | ||
317 | unsigned long ino = objp[0]; | ||
318 | __u32 generation = objp[1]; | ||
319 | struct inode *inode; | 317 | struct inode *inode; |
320 | struct dentry *result; | ||
321 | 318 | ||
322 | if (ino < EXT2_FIRST_INO(sb) && ino != EXT2_ROOT_INO) | 319 | if (ino < EXT2_FIRST_INO(sb) && ino != EXT2_ROOT_INO) |
323 | return ERR_PTR(-ESTALE); | 320 | return ERR_PTR(-ESTALE); |
@@ -338,15 +335,21 @@ static struct dentry *ext2_get_dentry(struct super_block *sb, void *vobjp) | |||
338 | iput(inode); | 335 | iput(inode); |
339 | return ERR_PTR(-ESTALE); | 336 | return ERR_PTR(-ESTALE); |
340 | } | 337 | } |
341 | /* now to find a dentry. | 338 | return inode; |
342 | * If possible, get a well-connected one | 339 | } |
343 | */ | 340 | |
344 | result = d_alloc_anon(inode); | 341 | static struct dentry *ext2_fh_to_dentry(struct super_block *sb, struct fid *fid, |
345 | if (!result) { | 342 | int fh_len, int fh_type) |
346 | iput(inode); | 343 | { |
347 | return ERR_PTR(-ENOMEM); | 344 | return generic_fh_to_dentry(sb, fid, fh_len, fh_type, |
348 | } | 345 | ext2_nfs_get_inode); |
349 | return result; | 346 | } |
347 | |||
348 | static struct dentry *ext2_fh_to_parent(struct super_block *sb, struct fid *fid, | ||
349 | int fh_len, int fh_type) | ||
350 | { | ||
351 | return generic_fh_to_parent(sb, fid, fh_len, fh_type, | ||
352 | ext2_nfs_get_inode); | ||
350 | } | 353 | } |
351 | 354 | ||
352 | /* Yes, most of these are left as NULL!! | 355 | /* Yes, most of these are left as NULL!! |
@@ -354,9 +357,10 @@ static struct dentry *ext2_get_dentry(struct super_block *sb, void *vobjp) | |||
354 | * systems, but can be improved upon. | 357 | * systems, but can be improved upon. |
355 | * Currently only get_parent is required. | 358 | * Currently only get_parent is required. |
356 | */ | 359 | */ |
357 | static struct export_operations ext2_export_ops = { | 360 | static const struct export_operations ext2_export_ops = { |
361 | .fh_to_dentry = ext2_fh_to_dentry, | ||
362 | .fh_to_parent = ext2_fh_to_parent, | ||
358 | .get_parent = ext2_get_parent, | 363 | .get_parent = ext2_get_parent, |
359 | .get_dentry = ext2_get_dentry, | ||
360 | }; | 364 | }; |
361 | 365 | ||
362 | static unsigned long get_sb_block(void **data) | 366 | static unsigned long get_sb_block(void **data) |
diff --git a/fs/ext3/super.c b/fs/ext3/super.c index 81868c0bc40e..de55da9e28ba 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c | |||
@@ -631,13 +631,10 @@ static int ext3_show_options(struct seq_file *seq, struct vfsmount *vfs) | |||
631 | } | 631 | } |
632 | 632 | ||
633 | 633 | ||
634 | static struct dentry *ext3_get_dentry(struct super_block *sb, void *vobjp) | 634 | static struct inode *ext3_nfs_get_inode(struct super_block *sb, |
635 | u64 ino, u32 generation) | ||
635 | { | 636 | { |
636 | __u32 *objp = vobjp; | ||
637 | unsigned long ino = objp[0]; | ||
638 | __u32 generation = objp[1]; | ||
639 | struct inode *inode; | 637 | struct inode *inode; |
640 | struct dentry *result; | ||
641 | 638 | ||
642 | if (ino < EXT3_FIRST_INO(sb) && ino != EXT3_ROOT_INO) | 639 | if (ino < EXT3_FIRST_INO(sb) && ino != EXT3_ROOT_INO) |
643 | return ERR_PTR(-ESTALE); | 640 | return ERR_PTR(-ESTALE); |
@@ -660,15 +657,22 @@ static struct dentry *ext3_get_dentry(struct super_block *sb, void *vobjp) | |||
660 | iput(inode); | 657 | iput(inode); |
661 | return ERR_PTR(-ESTALE); | 658 | return ERR_PTR(-ESTALE); |
662 | } | 659 | } |
663 | /* now to find a dentry. | 660 | |
664 | * If possible, get a well-connected one | 661 | return inode; |
665 | */ | 662 | } |
666 | result = d_alloc_anon(inode); | 663 | |
667 | if (!result) { | 664 | static struct dentry *ext3_fh_to_dentry(struct super_block *sb, struct fid *fid, |
668 | iput(inode); | 665 | int fh_len, int fh_type) |
669 | return ERR_PTR(-ENOMEM); | 666 | { |
670 | } | 667 | return generic_fh_to_dentry(sb, fid, fh_len, fh_type, |
671 | return result; | 668 | ext3_nfs_get_inode); |
669 | } | ||
670 | |||
671 | static struct dentry *ext3_fh_to_parent(struct super_block *sb, struct fid *fid, | ||
672 | int fh_len, int fh_type) | ||
673 | { | ||
674 | return generic_fh_to_parent(sb, fid, fh_len, fh_type, | ||
675 | ext3_nfs_get_inode); | ||
672 | } | 676 | } |
673 | 677 | ||
674 | #ifdef CONFIG_QUOTA | 678 | #ifdef CONFIG_QUOTA |
@@ -737,9 +741,10 @@ static const struct super_operations ext3_sops = { | |||
737 | #endif | 741 | #endif |
738 | }; | 742 | }; |
739 | 743 | ||
740 | static struct export_operations ext3_export_ops = { | 744 | static const struct export_operations ext3_export_ops = { |
745 | .fh_to_dentry = ext3_fh_to_dentry, | ||
746 | .fh_to_parent = ext3_fh_to_parent, | ||
741 | .get_parent = ext3_get_parent, | 747 | .get_parent = ext3_get_parent, |
742 | .get_dentry = ext3_get_dentry, | ||
743 | }; | 748 | }; |
744 | 749 | ||
745 | enum { | 750 | enum { |
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index b11e9e2bcd01..8031dc0e24e5 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
@@ -686,13 +686,10 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs) | |||
686 | } | 686 | } |
687 | 687 | ||
688 | 688 | ||
689 | static struct dentry *ext4_get_dentry(struct super_block *sb, void *vobjp) | 689 | static struct inode *ext4_nfs_get_inode(struct super_block *sb, |
690 | u64 ino, u32 generation) | ||
690 | { | 691 | { |
691 | __u32 *objp = vobjp; | ||
692 | unsigned long ino = objp[0]; | ||
693 | __u32 generation = objp[1]; | ||
694 | struct inode *inode; | 692 | struct inode *inode; |
695 | struct dentry *result; | ||
696 | 693 | ||
697 | if (ino < EXT4_FIRST_INO(sb) && ino != EXT4_ROOT_INO) | 694 | if (ino < EXT4_FIRST_INO(sb) && ino != EXT4_ROOT_INO) |
698 | return ERR_PTR(-ESTALE); | 695 | return ERR_PTR(-ESTALE); |
@@ -715,15 +712,22 @@ static struct dentry *ext4_get_dentry(struct super_block *sb, void *vobjp) | |||
715 | iput(inode); | 712 | iput(inode); |
716 | return ERR_PTR(-ESTALE); | 713 | return ERR_PTR(-ESTALE); |
717 | } | 714 | } |
718 | /* now to find a dentry. | 715 | |
719 | * If possible, get a well-connected one | 716 | return inode; |
720 | */ | 717 | } |
721 | result = d_alloc_anon(inode); | 718 | |
722 | if (!result) { | 719 | static struct dentry *ext4_fh_to_dentry(struct super_block *sb, struct fid *fid, |
723 | iput(inode); | 720 | int fh_len, int fh_type) |
724 | return ERR_PTR(-ENOMEM); | 721 | { |
725 | } | 722 | return generic_fh_to_dentry(sb, fid, fh_len, fh_type, |
726 | return result; | 723 | ext4_nfs_get_inode); |
724 | } | ||
725 | |||
726 | static struct dentry *ext4_fh_to_parent(struct super_block *sb, struct fid *fid, | ||
727 | int fh_len, int fh_type) | ||
728 | { | ||
729 | return generic_fh_to_parent(sb, fid, fh_len, fh_type, | ||
730 | ext4_nfs_get_inode); | ||
727 | } | 731 | } |
728 | 732 | ||
729 | #ifdef CONFIG_QUOTA | 733 | #ifdef CONFIG_QUOTA |
@@ -792,9 +796,10 @@ static const struct super_operations ext4_sops = { | |||
792 | #endif | 796 | #endif |
793 | }; | 797 | }; |
794 | 798 | ||
795 | static struct export_operations ext4_export_ops = { | 799 | static const struct export_operations ext4_export_ops = { |
800 | .fh_to_dentry = ext4_fh_to_dentry, | ||
801 | .fh_to_parent = ext4_fh_to_parent, | ||
796 | .get_parent = ext4_get_parent, | 802 | .get_parent = ext4_get_parent, |
797 | .get_dentry = ext4_get_dentry, | ||
798 | }; | 803 | }; |
799 | 804 | ||
800 | enum { | 805 | enum { |
diff --git a/fs/fat/inode.c b/fs/fat/inode.c index c0c5e9c55b58..920a576e1c25 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c | |||
@@ -653,24 +653,15 @@ static const struct super_operations fat_sops = { | |||
653 | * of i_logstart is used to store the directory entry offset. | 653 | * of i_logstart is used to store the directory entry offset. |
654 | */ | 654 | */ |
655 | 655 | ||
656 | static struct dentry * | 656 | static struct dentry *fat_fh_to_dentry(struct super_block *sb, |
657 | fat_decode_fh(struct super_block *sb, __u32 *fh, int len, int fhtype, | 657 | struct fid *fid, int fh_len, int fh_type) |
658 | int (*acceptable)(void *context, struct dentry *de), | ||
659 | void *context) | ||
660 | { | ||
661 | if (fhtype != 3) | ||
662 | return ERR_PTR(-ESTALE); | ||
663 | if (len < 5) | ||
664 | return ERR_PTR(-ESTALE); | ||
665 | |||
666 | return sb->s_export_op->find_exported_dentry(sb, fh, NULL, acceptable, context); | ||
667 | } | ||
668 | |||
669 | static struct dentry *fat_get_dentry(struct super_block *sb, void *inump) | ||
670 | { | 658 | { |
671 | struct inode *inode = NULL; | 659 | struct inode *inode = NULL; |
672 | struct dentry *result; | 660 | struct dentry *result; |
673 | __u32 *fh = inump; | 661 | u32 *fh = fid->raw; |
662 | |||
663 | if (fh_len < 5 || fh_type != 3) | ||
664 | return NULL; | ||
674 | 665 | ||
675 | inode = iget(sb, fh[0]); | 666 | inode = iget(sb, fh[0]); |
676 | if (!inode || is_bad_inode(inode) || inode->i_generation != fh[1]) { | 667 | if (!inode || is_bad_inode(inode) || inode->i_generation != fh[1]) { |
@@ -783,10 +774,9 @@ out: | |||
783 | return parent; | 774 | return parent; |
784 | } | 775 | } |
785 | 776 | ||
786 | static struct export_operations fat_export_ops = { | 777 | static const struct export_operations fat_export_ops = { |
787 | .decode_fh = fat_decode_fh, | ||
788 | .encode_fh = fat_encode_fh, | 778 | .encode_fh = fat_encode_fh, |
789 | .get_dentry = fat_get_dentry, | 779 | .fh_to_dentry = fat_fh_to_dentry, |
790 | .get_parent = fat_get_parent, | 780 | .get_parent = fat_get_parent, |
791 | }; | 781 | }; |
792 | 782 | ||
diff --git a/fs/gfs2/ops_export.c b/fs/gfs2/ops_export.c index e2d1347796a9..b9da62348a87 100644 --- a/fs/gfs2/ops_export.c +++ b/fs/gfs2/ops_export.c | |||
@@ -31,40 +31,6 @@ | |||
31 | #define GFS2_LARGE_FH_SIZE 8 | 31 | #define GFS2_LARGE_FH_SIZE 8 |
32 | #define GFS2_OLD_FH_SIZE 10 | 32 | #define GFS2_OLD_FH_SIZE 10 |
33 | 33 | ||
34 | static struct dentry *gfs2_decode_fh(struct super_block *sb, | ||
35 | __u32 *p, | ||
36 | int fh_len, | ||
37 | int fh_type, | ||
38 | int (*acceptable)(void *context, | ||
39 | struct dentry *dentry), | ||
40 | void *context) | ||
41 | { | ||
42 | __be32 *fh = (__force __be32 *)p; | ||
43 | struct gfs2_inum_host inum, parent; | ||
44 | |||
45 | memset(&parent, 0, sizeof(struct gfs2_inum)); | ||
46 | |||
47 | switch (fh_len) { | ||
48 | case GFS2_LARGE_FH_SIZE: | ||
49 | case GFS2_OLD_FH_SIZE: | ||
50 | parent.no_formal_ino = ((u64)be32_to_cpu(fh[4])) << 32; | ||
51 | parent.no_formal_ino |= be32_to_cpu(fh[5]); | ||
52 | parent.no_addr = ((u64)be32_to_cpu(fh[6])) << 32; | ||
53 | parent.no_addr |= be32_to_cpu(fh[7]); | ||
54 | case GFS2_SMALL_FH_SIZE: | ||
55 | inum.no_formal_ino = ((u64)be32_to_cpu(fh[0])) << 32; | ||
56 | inum.no_formal_ino |= be32_to_cpu(fh[1]); | ||
57 | inum.no_addr = ((u64)be32_to_cpu(fh[2])) << 32; | ||
58 | inum.no_addr |= be32_to_cpu(fh[3]); | ||
59 | break; | ||
60 | default: | ||
61 | return NULL; | ||
62 | } | ||
63 | |||
64 | return gfs2_export_ops.find_exported_dentry(sb, &inum, &parent, | ||
65 | acceptable, context); | ||
66 | } | ||
67 | |||
68 | static int gfs2_encode_fh(struct dentry *dentry, __u32 *p, int *len, | 34 | static int gfs2_encode_fh(struct dentry *dentry, __u32 *p, int *len, |
69 | int connectable) | 35 | int connectable) |
70 | { | 36 | { |
@@ -189,10 +155,10 @@ static struct dentry *gfs2_get_parent(struct dentry *child) | |||
189 | return dentry; | 155 | return dentry; |
190 | } | 156 | } |
191 | 157 | ||
192 | static struct dentry *gfs2_get_dentry(struct super_block *sb, void *inum_obj) | 158 | static struct dentry *gfs2_get_dentry(struct super_block *sb, |
159 | struct gfs2_inum_host *inum) | ||
193 | { | 160 | { |
194 | struct gfs2_sbd *sdp = sb->s_fs_info; | 161 | struct gfs2_sbd *sdp = sb->s_fs_info; |
195 | struct gfs2_inum_host *inum = inum_obj; | ||
196 | struct gfs2_holder i_gh, ri_gh, rgd_gh; | 162 | struct gfs2_holder i_gh, ri_gh, rgd_gh; |
197 | struct gfs2_rgrpd *rgd; | 163 | struct gfs2_rgrpd *rgd; |
198 | struct inode *inode; | 164 | struct inode *inode; |
@@ -289,11 +255,50 @@ fail: | |||
289 | return ERR_PTR(error); | 255 | return ERR_PTR(error); |
290 | } | 256 | } |
291 | 257 | ||
292 | struct export_operations gfs2_export_ops = { | 258 | static struct dentry *gfs2_fh_to_dentry(struct super_block *sb, struct fid *fid, |
293 | .decode_fh = gfs2_decode_fh, | 259 | int fh_len, int fh_type) |
260 | { | ||
261 | struct gfs2_inum_host this; | ||
262 | __be32 *fh = (__force __be32 *)fid->raw; | ||
263 | |||
264 | switch (fh_type) { | ||
265 | case GFS2_SMALL_FH_SIZE: | ||
266 | case GFS2_LARGE_FH_SIZE: | ||
267 | case GFS2_OLD_FH_SIZE: | ||
268 | this.no_formal_ino = ((u64)be32_to_cpu(fh[0])) << 32; | ||
269 | this.no_formal_ino |= be32_to_cpu(fh[1]); | ||
270 | this.no_addr = ((u64)be32_to_cpu(fh[2])) << 32; | ||
271 | this.no_addr |= be32_to_cpu(fh[3]); | ||
272 | return gfs2_get_dentry(sb, &this); | ||
273 | default: | ||
274 | return NULL; | ||
275 | } | ||
276 | } | ||
277 | |||
278 | static struct dentry *gfs2_fh_to_parent(struct super_block *sb, struct fid *fid, | ||
279 | int fh_len, int fh_type) | ||
280 | { | ||
281 | struct gfs2_inum_host parent; | ||
282 | __be32 *fh = (__force __be32 *)fid->raw; | ||
283 | |||
284 | switch (fh_type) { | ||
285 | case GFS2_LARGE_FH_SIZE: | ||
286 | case GFS2_OLD_FH_SIZE: | ||
287 | parent.no_formal_ino = ((u64)be32_to_cpu(fh[4])) << 32; | ||
288 | parent.no_formal_ino |= be32_to_cpu(fh[5]); | ||
289 | parent.no_addr = ((u64)be32_to_cpu(fh[6])) << 32; | ||
290 | parent.no_addr |= be32_to_cpu(fh[7]); | ||
291 | return gfs2_get_dentry(sb, &parent); | ||
292 | default: | ||
293 | return NULL; | ||
294 | } | ||
295 | } | ||
296 | |||
297 | const struct export_operations gfs2_export_ops = { | ||
294 | .encode_fh = gfs2_encode_fh, | 298 | .encode_fh = gfs2_encode_fh, |
299 | .fh_to_dentry = gfs2_fh_to_dentry, | ||
300 | .fh_to_parent = gfs2_fh_to_parent, | ||
295 | .get_name = gfs2_get_name, | 301 | .get_name = gfs2_get_name, |
296 | .get_parent = gfs2_get_parent, | 302 | .get_parent = gfs2_get_parent, |
297 | .get_dentry = gfs2_get_dentry, | ||
298 | }; | 303 | }; |
299 | 304 | ||
diff --git a/fs/gfs2/ops_fstype.h b/fs/gfs2/ops_fstype.h index 407029b3b2b3..da8490511836 100644 --- a/fs/gfs2/ops_fstype.h +++ b/fs/gfs2/ops_fstype.h | |||
@@ -14,6 +14,6 @@ | |||
14 | 14 | ||
15 | extern struct file_system_type gfs2_fs_type; | 15 | extern struct file_system_type gfs2_fs_type; |
16 | extern struct file_system_type gfs2meta_fs_type; | 16 | extern struct file_system_type gfs2meta_fs_type; |
17 | extern struct export_operations gfs2_export_ops; | 17 | extern const struct export_operations gfs2_export_ops; |
18 | 18 | ||
19 | #endif /* __OPS_FSTYPE_DOT_H__ */ | 19 | #endif /* __OPS_FSTYPE_DOT_H__ */ |
diff --git a/fs/inotify.c b/fs/inotify.c index 7457501b9565..2c5b92152876 100644 --- a/fs/inotify.c +++ b/fs/inotify.c | |||
@@ -667,6 +667,49 @@ out: | |||
667 | EXPORT_SYMBOL_GPL(inotify_add_watch); | 667 | EXPORT_SYMBOL_GPL(inotify_add_watch); |
668 | 668 | ||
669 | /** | 669 | /** |
670 | * inotify_clone_watch - put the watch next to existing one | ||
671 | * @old: already installed watch | ||
672 | * @new: new watch | ||
673 | * | ||
674 | * Caller must hold the inotify_mutex of inode we are dealing with; | ||
675 | * it is expected to remove the old watch before unlocking the inode. | ||
676 | */ | ||
677 | s32 inotify_clone_watch(struct inotify_watch *old, struct inotify_watch *new) | ||
678 | { | ||
679 | struct inotify_handle *ih = old->ih; | ||
680 | int ret = 0; | ||
681 | |||
682 | new->mask = old->mask; | ||
683 | new->ih = ih; | ||
684 | |||
685 | mutex_lock(&ih->mutex); | ||
686 | |||
687 | /* Initialize a new watch */ | ||
688 | ret = inotify_handle_get_wd(ih, new); | ||
689 | if (unlikely(ret)) | ||
690 | goto out; | ||
691 | ret = new->wd; | ||
692 | |||
693 | get_inotify_handle(ih); | ||
694 | |||
695 | new->inode = igrab(old->inode); | ||
696 | |||
697 | list_add(&new->h_list, &ih->watches); | ||
698 | list_add(&new->i_list, &old->inode->inotify_watches); | ||
699 | out: | ||
700 | mutex_unlock(&ih->mutex); | ||
701 | return ret; | ||
702 | } | ||
703 | |||
704 | void inotify_evict_watch(struct inotify_watch *watch) | ||
705 | { | ||
706 | get_inotify_watch(watch); | ||
707 | mutex_lock(&watch->ih->mutex); | ||
708 | inotify_remove_watch_locked(watch->ih, watch); | ||
709 | mutex_unlock(&watch->ih->mutex); | ||
710 | } | ||
711 | |||
712 | /** | ||
670 | * inotify_rm_wd - remove a watch from an inotify instance | 713 | * inotify_rm_wd - remove a watch from an inotify instance |
671 | * @ih: inotify handle | 714 | * @ih: inotify handle |
672 | * @wd: watch descriptor to remove | 715 | * @wd: watch descriptor to remove |
diff --git a/fs/isofs/export.c b/fs/isofs/export.c index 4af856a7fda7..29f9753ae5e5 100644 --- a/fs/isofs/export.c +++ b/fs/isofs/export.c | |||
@@ -42,16 +42,6 @@ isofs_export_iget(struct super_block *sb, | |||
42 | return result; | 42 | return result; |
43 | } | 43 | } |
44 | 44 | ||
45 | static struct dentry * | ||
46 | isofs_export_get_dentry(struct super_block *sb, void *vobjp) | ||
47 | { | ||
48 | __u32 *objp = vobjp; | ||
49 | unsigned long block = objp[0]; | ||
50 | unsigned long offset = objp[1]; | ||
51 | __u32 generation = objp[2]; | ||
52 | return isofs_export_iget(sb, block, offset, generation); | ||
53 | } | ||
54 | |||
55 | /* This function is surprisingly simple. The trick is understanding | 45 | /* This function is surprisingly simple. The trick is understanding |
56 | * that "child" is always a directory. So, to find its parent, you | 46 | * that "child" is always a directory. So, to find its parent, you |
57 | * simply need to find its ".." entry, normalize its block and offset, | 47 | * simply need to find its ".." entry, normalize its block and offset, |
@@ -182,43 +172,44 @@ isofs_export_encode_fh(struct dentry *dentry, | |||
182 | return type; | 172 | return type; |
183 | } | 173 | } |
184 | 174 | ||
175 | struct isofs_fid { | ||
176 | u32 block; | ||
177 | u16 offset; | ||
178 | u16 parent_offset; | ||
179 | u32 generation; | ||
180 | u32 parent_block; | ||
181 | u32 parent_generation; | ||
182 | }; | ||
185 | 183 | ||
186 | static struct dentry * | 184 | static struct dentry *isofs_fh_to_dentry(struct super_block *sb, |
187 | isofs_export_decode_fh(struct super_block *sb, | 185 | struct fid *fid, int fh_len, int fh_type) |
188 | __u32 *fh32, | ||
189 | int fh_len, | ||
190 | int fileid_type, | ||
191 | int (*acceptable)(void *context, struct dentry *de), | ||
192 | void *context) | ||
193 | { | 186 | { |
194 | __u16 *fh16 = (__u16*)fh32; | 187 | struct isofs_fid *ifid = (struct isofs_fid *)fid; |
195 | __u32 child[3]; /* The child is what triggered all this. */ | ||
196 | __u32 parent[3]; /* The parent is just along for the ride. */ | ||
197 | 188 | ||
198 | if (fh_len < 3 || fileid_type > 2) | 189 | if (fh_len < 3 || fh_type > 2) |
199 | return NULL; | 190 | return NULL; |
200 | 191 | ||
201 | child[0] = fh32[0]; | 192 | return isofs_export_iget(sb, ifid->block, ifid->offset, |
202 | child[1] = fh16[2]; /* fh16 [sic] */ | 193 | ifid->generation); |
203 | child[2] = fh32[2]; | ||
204 | |||
205 | parent[0] = 0; | ||
206 | parent[1] = 0; | ||
207 | parent[2] = 0; | ||
208 | if (fileid_type == 2) { | ||
209 | if (fh_len > 2) parent[0] = fh32[3]; | ||
210 | parent[1] = fh16[3]; /* fh16 [sic] */ | ||
211 | if (fh_len > 4) parent[2] = fh32[4]; | ||
212 | } | ||
213 | |||
214 | return sb->s_export_op->find_exported_dentry(sb, child, parent, | ||
215 | acceptable, context); | ||
216 | } | 194 | } |
217 | 195 | ||
196 | static struct dentry *isofs_fh_to_parent(struct super_block *sb, | ||
197 | struct fid *fid, int fh_len, int fh_type) | ||
198 | { | ||
199 | struct isofs_fid *ifid = (struct isofs_fid *)fid; | ||
200 | |||
201 | if (fh_type != 2) | ||
202 | return NULL; | ||
203 | |||
204 | return isofs_export_iget(sb, | ||
205 | fh_len > 2 ? ifid->parent_block : 0, | ||
206 | ifid->parent_offset, | ||
207 | fh_len > 4 ? ifid->parent_generation : 0); | ||
208 | } | ||
218 | 209 | ||
219 | struct export_operations isofs_export_ops = { | 210 | const struct export_operations isofs_export_ops = { |
220 | .decode_fh = isofs_export_decode_fh, | ||
221 | .encode_fh = isofs_export_encode_fh, | 211 | .encode_fh = isofs_export_encode_fh, |
222 | .get_dentry = isofs_export_get_dentry, | 212 | .fh_to_dentry = isofs_fh_to_dentry, |
213 | .fh_to_parent = isofs_fh_to_parent, | ||
223 | .get_parent = isofs_export_get_parent, | 214 | .get_parent = isofs_export_get_parent, |
224 | }; | 215 | }; |
diff --git a/fs/isofs/isofs.h b/fs/isofs/isofs.h index a07e67b1ea7f..f3213f9f89af 100644 --- a/fs/isofs/isofs.h +++ b/fs/isofs/isofs.h | |||
@@ -178,4 +178,4 @@ isofs_normalize_block_and_offset(struct iso_directory_record* de, | |||
178 | extern const struct inode_operations isofs_dir_inode_operations; | 178 | extern const struct inode_operations isofs_dir_inode_operations; |
179 | extern const struct file_operations isofs_dir_operations; | 179 | extern const struct file_operations isofs_dir_operations; |
180 | extern const struct address_space_operations isofs_symlink_aops; | 180 | extern const struct address_space_operations isofs_symlink_aops; |
181 | extern struct export_operations isofs_export_ops; | 181 | extern const struct export_operations isofs_export_ops; |
diff --git a/fs/jfs/jfs_inode.h b/fs/jfs/jfs_inode.h index f0ec72b263f1..8e2cf2cde185 100644 --- a/fs/jfs/jfs_inode.h +++ b/fs/jfs/jfs_inode.h | |||
@@ -18,6 +18,8 @@ | |||
18 | #ifndef _H_JFS_INODE | 18 | #ifndef _H_JFS_INODE |
19 | #define _H_JFS_INODE | 19 | #define _H_JFS_INODE |
20 | 20 | ||
21 | struct fid; | ||
22 | |||
21 | extern struct inode *ialloc(struct inode *, umode_t); | 23 | extern struct inode *ialloc(struct inode *, umode_t); |
22 | extern int jfs_fsync(struct file *, struct dentry *, int); | 24 | extern int jfs_fsync(struct file *, struct dentry *, int); |
23 | extern int jfs_ioctl(struct inode *, struct file *, | 25 | extern int jfs_ioctl(struct inode *, struct file *, |
@@ -32,7 +34,10 @@ extern void jfs_truncate_nolock(struct inode *, loff_t); | |||
32 | extern void jfs_free_zero_link(struct inode *); | 34 | extern void jfs_free_zero_link(struct inode *); |
33 | extern struct dentry *jfs_get_parent(struct dentry *dentry); | 35 | extern struct dentry *jfs_get_parent(struct dentry *dentry); |
34 | extern void jfs_get_inode_flags(struct jfs_inode_info *); | 36 | extern void jfs_get_inode_flags(struct jfs_inode_info *); |
35 | extern struct dentry *jfs_get_dentry(struct super_block *sb, void *vobjp); | 37 | extern struct dentry *jfs_fh_to_dentry(struct super_block *sb, struct fid *fid, |
38 | int fh_len, int fh_type); | ||
39 | extern struct dentry *jfs_fh_to_parent(struct super_block *sb, struct fid *fid, | ||
40 | int fh_len, int fh_type); | ||
36 | extern void jfs_set_inode_flags(struct inode *); | 41 | extern void jfs_set_inode_flags(struct inode *); |
37 | extern int jfs_get_block(struct inode *, sector_t, struct buffer_head *, int); | 42 | extern int jfs_get_block(struct inode *, sector_t, struct buffer_head *, int); |
38 | 43 | ||
diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c index 932797ba433b..4e0a8493cef6 100644 --- a/fs/jfs/namei.c +++ b/fs/jfs/namei.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/fs.h> | 20 | #include <linux/fs.h> |
21 | #include <linux/ctype.h> | 21 | #include <linux/ctype.h> |
22 | #include <linux/quotaops.h> | 22 | #include <linux/quotaops.h> |
23 | #include <linux/exportfs.h> | ||
23 | #include "jfs_incore.h" | 24 | #include "jfs_incore.h" |
24 | #include "jfs_superblock.h" | 25 | #include "jfs_superblock.h" |
25 | #include "jfs_inode.h" | 26 | #include "jfs_inode.h" |
@@ -1477,13 +1478,10 @@ static struct dentry *jfs_lookup(struct inode *dip, struct dentry *dentry, struc | |||
1477 | return dentry; | 1478 | return dentry; |
1478 | } | 1479 | } |
1479 | 1480 | ||
1480 | struct dentry *jfs_get_dentry(struct super_block *sb, void *vobjp) | 1481 | static struct inode *jfs_nfs_get_inode(struct super_block *sb, |
1482 | u64 ino, u32 generation) | ||
1481 | { | 1483 | { |
1482 | __u32 *objp = vobjp; | ||
1483 | unsigned long ino = objp[0]; | ||
1484 | __u32 generation = objp[1]; | ||
1485 | struct inode *inode; | 1484 | struct inode *inode; |
1486 | struct dentry *result; | ||
1487 | 1485 | ||
1488 | if (ino == 0) | 1486 | if (ino == 0) |
1489 | return ERR_PTR(-ESTALE); | 1487 | return ERR_PTR(-ESTALE); |
@@ -1493,20 +1491,25 @@ struct dentry *jfs_get_dentry(struct super_block *sb, void *vobjp) | |||
1493 | 1491 | ||
1494 | if (is_bad_inode(inode) || | 1492 | if (is_bad_inode(inode) || |
1495 | (generation && inode->i_generation != generation)) { | 1493 | (generation && inode->i_generation != generation)) { |
1496 | result = ERR_PTR(-ESTALE); | 1494 | iput(inode); |
1497 | goto out_iput; | 1495 | return ERR_PTR(-ESTALE); |
1498 | } | 1496 | } |
1499 | 1497 | ||
1500 | result = d_alloc_anon(inode); | 1498 | return inode; |
1501 | if (!result) { | 1499 | } |
1502 | result = ERR_PTR(-ENOMEM); | ||
1503 | goto out_iput; | ||
1504 | } | ||
1505 | return result; | ||
1506 | 1500 | ||
1507 | out_iput: | 1501 | struct dentry *jfs_fh_to_dentry(struct super_block *sb, struct fid *fid, |
1508 | iput(inode); | 1502 | int fh_len, int fh_type) |
1509 | return result; | 1503 | { |
1504 | return generic_fh_to_dentry(sb, fid, fh_len, fh_type, | ||
1505 | jfs_nfs_get_inode); | ||
1506 | } | ||
1507 | |||
1508 | struct dentry *jfs_fh_to_parent(struct super_block *sb, struct fid *fid, | ||
1509 | int fh_len, int fh_type) | ||
1510 | { | ||
1511 | return generic_fh_to_parent(sb, fid, fh_len, fh_type, | ||
1512 | jfs_nfs_get_inode); | ||
1510 | } | 1513 | } |
1511 | 1514 | ||
1512 | struct dentry *jfs_get_parent(struct dentry *dentry) | 1515 | struct dentry *jfs_get_parent(struct dentry *dentry) |
diff --git a/fs/jfs/super.c b/fs/jfs/super.c index cff60c171943..314bb4ff1ba8 100644 --- a/fs/jfs/super.c +++ b/fs/jfs/super.c | |||
@@ -48,7 +48,7 @@ MODULE_LICENSE("GPL"); | |||
48 | static struct kmem_cache * jfs_inode_cachep; | 48 | static struct kmem_cache * jfs_inode_cachep; |
49 | 49 | ||
50 | static const struct super_operations jfs_super_operations; | 50 | static const struct super_operations jfs_super_operations; |
51 | static struct export_operations jfs_export_operations; | 51 | static const struct export_operations jfs_export_operations; |
52 | static struct file_system_type jfs_fs_type; | 52 | static struct file_system_type jfs_fs_type; |
53 | 53 | ||
54 | #define MAX_COMMIT_THREADS 64 | 54 | #define MAX_COMMIT_THREADS 64 |
@@ -737,8 +737,9 @@ static const struct super_operations jfs_super_operations = { | |||
737 | #endif | 737 | #endif |
738 | }; | 738 | }; |
739 | 739 | ||
740 | static struct export_operations jfs_export_operations = { | 740 | static const struct export_operations jfs_export_operations = { |
741 | .get_dentry = jfs_get_dentry, | 741 | .fh_to_dentry = jfs_fh_to_dentry, |
742 | .fh_to_parent = jfs_fh_to_parent, | ||
742 | .get_parent = jfs_get_parent, | 743 | .get_parent = jfs_get_parent, |
743 | }; | 744 | }; |
744 | 745 | ||
diff --git a/fs/libfs.c b/fs/libfs.c index ae51481e45e5..6e68b700958d 100644 --- a/fs/libfs.c +++ b/fs/libfs.c | |||
@@ -8,6 +8,7 @@ | |||
8 | #include <linux/mount.h> | 8 | #include <linux/mount.h> |
9 | #include <linux/vfs.h> | 9 | #include <linux/vfs.h> |
10 | #include <linux/mutex.h> | 10 | #include <linux/mutex.h> |
11 | #include <linux/exportfs.h> | ||
11 | 12 | ||
12 | #include <asm/uaccess.h> | 13 | #include <asm/uaccess.h> |
13 | 14 | ||
@@ -678,6 +679,93 @@ out: | |||
678 | return ret; | 679 | return ret; |
679 | } | 680 | } |
680 | 681 | ||
682 | /* | ||
683 | * This is what d_alloc_anon should have been. Once the exportfs | ||
684 | * argument transition has been finished I will update d_alloc_anon | ||
685 | * to this prototype and this wrapper will go away. --hch | ||
686 | */ | ||
687 | static struct dentry *exportfs_d_alloc(struct inode *inode) | ||
688 | { | ||
689 | struct dentry *dentry; | ||
690 | |||
691 | if (!inode) | ||
692 | return NULL; | ||
693 | if (IS_ERR(inode)) | ||
694 | return ERR_PTR(PTR_ERR(inode)); | ||
695 | |||
696 | dentry = d_alloc_anon(inode); | ||
697 | if (!dentry) { | ||
698 | iput(inode); | ||
699 | dentry = ERR_PTR(-ENOMEM); | ||
700 | } | ||
701 | return dentry; | ||
702 | } | ||
703 | |||
704 | /** | ||
705 | * generic_fh_to_dentry - generic helper for the fh_to_dentry export operation | ||
706 | * @sb: filesystem to do the file handle conversion on | ||
707 | * @fid: file handle to convert | ||
708 | * @fh_len: length of the file handle in bytes | ||
709 | * @fh_type: type of file handle | ||
710 | * @get_inode: filesystem callback to retrieve inode | ||
711 | * | ||
712 | * This function decodes @fid as long as it has one of the well-known | ||
713 | * Linux filehandle types and calls @get_inode on it to retrieve the | ||
714 | * inode for the object specified in the file handle. | ||
715 | */ | ||
716 | struct dentry *generic_fh_to_dentry(struct super_block *sb, struct fid *fid, | ||
717 | int fh_len, int fh_type, struct inode *(*get_inode) | ||
718 | (struct super_block *sb, u64 ino, u32 gen)) | ||
719 | { | ||
720 | struct inode *inode = NULL; | ||
721 | |||
722 | if (fh_len < 2) | ||
723 | return NULL; | ||
724 | |||
725 | switch (fh_type) { | ||
726 | case FILEID_INO32_GEN: | ||
727 | case FILEID_INO32_GEN_PARENT: | ||
728 | inode = get_inode(sb, fid->i32.ino, fid->i32.gen); | ||
729 | break; | ||
730 | } | ||
731 | |||
732 | return exportfs_d_alloc(inode); | ||
733 | } | ||
734 | EXPORT_SYMBOL_GPL(generic_fh_to_dentry); | ||
735 | |||
736 | /** | ||
737 | * generic_fh_to_dentry - generic helper for the fh_to_parent export operation | ||
738 | * @sb: filesystem to do the file handle conversion on | ||
739 | * @fid: file handle to convert | ||
740 | * @fh_len: length of the file handle in bytes | ||
741 | * @fh_type: type of file handle | ||
742 | * @get_inode: filesystem callback to retrieve inode | ||
743 | * | ||
744 | * This function decodes @fid as long as it has one of the well-known | ||
745 | * Linux filehandle types and calls @get_inode on it to retrieve the | ||
746 | * inode for the _parent_ object specified in the file handle if it | ||
747 | * is specified in the file handle, or NULL otherwise. | ||
748 | */ | ||
749 | struct dentry *generic_fh_to_parent(struct super_block *sb, struct fid *fid, | ||
750 | int fh_len, int fh_type, struct inode *(*get_inode) | ||
751 | (struct super_block *sb, u64 ino, u32 gen)) | ||
752 | { | ||
753 | struct inode *inode = NULL; | ||
754 | |||
755 | if (fh_len <= 2) | ||
756 | return NULL; | ||
757 | |||
758 | switch (fh_type) { | ||
759 | case FILEID_INO32_GEN_PARENT: | ||
760 | inode = get_inode(sb, fid->i32.parent_ino, | ||
761 | (fh_len > 3 ? fid->i32.parent_gen : 0)); | ||
762 | break; | ||
763 | } | ||
764 | |||
765 | return exportfs_d_alloc(inode); | ||
766 | } | ||
767 | EXPORT_SYMBOL_GPL(generic_fh_to_parent); | ||
768 | |||
681 | EXPORT_SYMBOL(dcache_dir_close); | 769 | EXPORT_SYMBOL(dcache_dir_close); |
682 | EXPORT_SYMBOL(dcache_dir_lseek); | 770 | EXPORT_SYMBOL(dcache_dir_lseek); |
683 | EXPORT_SYMBOL(dcache_dir_open); | 771 | EXPORT_SYMBOL(dcache_dir_open); |
diff --git a/fs/namei.c b/fs/namei.c index 1e5c71669164..3b993db26cee 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -1174,7 +1174,7 @@ static int fastcall do_path_lookup(int dfd, const char *name, | |||
1174 | out: | 1174 | out: |
1175 | if (unlikely(!retval && !audit_dummy_context() && nd->dentry && | 1175 | if (unlikely(!retval && !audit_dummy_context() && nd->dentry && |
1176 | nd->dentry->d_inode)) | 1176 | nd->dentry->d_inode)) |
1177 | audit_inode(name, nd->dentry->d_inode); | 1177 | audit_inode(name, nd->dentry); |
1178 | out_fail: | 1178 | out_fail: |
1179 | return retval; | 1179 | return retval; |
1180 | 1180 | ||
@@ -1214,7 +1214,7 @@ int vfs_path_lookup(struct dentry *dentry, struct vfsmount *mnt, | |||
1214 | retval = path_walk(name, nd); | 1214 | retval = path_walk(name, nd); |
1215 | if (unlikely(!retval && !audit_dummy_context() && nd->dentry && | 1215 | if (unlikely(!retval && !audit_dummy_context() && nd->dentry && |
1216 | nd->dentry->d_inode)) | 1216 | nd->dentry->d_inode)) |
1217 | audit_inode(name, nd->dentry->d_inode); | 1217 | audit_inode(name, nd->dentry); |
1218 | 1218 | ||
1219 | return retval; | 1219 | return retval; |
1220 | 1220 | ||
@@ -1469,7 +1469,7 @@ static int may_delete(struct inode *dir,struct dentry *victim,int isdir) | |||
1469 | return -ENOENT; | 1469 | return -ENOENT; |
1470 | 1470 | ||
1471 | BUG_ON(victim->d_parent->d_inode != dir); | 1471 | BUG_ON(victim->d_parent->d_inode != dir); |
1472 | audit_inode_child(victim->d_name.name, victim->d_inode, dir); | 1472 | audit_inode_child(victim->d_name.name, victim, dir); |
1473 | 1473 | ||
1474 | error = permission(dir,MAY_WRITE | MAY_EXEC, NULL); | 1474 | error = permission(dir,MAY_WRITE | MAY_EXEC, NULL); |
1475 | if (error) | 1475 | if (error) |
@@ -1783,7 +1783,7 @@ do_last: | |||
1783 | * It already exists. | 1783 | * It already exists. |
1784 | */ | 1784 | */ |
1785 | mutex_unlock(&dir->d_inode->i_mutex); | 1785 | mutex_unlock(&dir->d_inode->i_mutex); |
1786 | audit_inode(pathname, path.dentry->d_inode); | 1786 | audit_inode(pathname, path.dentry); |
1787 | 1787 | ||
1788 | error = -EEXIST; | 1788 | error = -EEXIST; |
1789 | if (flag & O_EXCL) | 1789 | if (flag & O_EXCL) |
@@ -2562,7 +2562,7 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
2562 | if (!error) { | 2562 | if (!error) { |
2563 | const char *new_name = old_dentry->d_name.name; | 2563 | const char *new_name = old_dentry->d_name.name; |
2564 | fsnotify_move(old_dir, new_dir, old_name, new_name, is_dir, | 2564 | fsnotify_move(old_dir, new_dir, old_name, new_name, is_dir, |
2565 | new_dentry->d_inode, old_dentry->d_inode); | 2565 | new_dentry->d_inode, old_dentry); |
2566 | } | 2566 | } |
2567 | fsnotify_oldname_free(old_name); | 2567 | fsnotify_oldname_free(old_name); |
2568 | 2568 | ||
diff --git a/fs/namespace.c b/fs/namespace.c index 860752998fb3..06083885b21e 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
@@ -246,7 +246,7 @@ static struct vfsmount *clone_mnt(struct vfsmount *old, struct dentry *root, | |||
246 | list_add(&mnt->mnt_slave, &old->mnt_slave_list); | 246 | list_add(&mnt->mnt_slave, &old->mnt_slave_list); |
247 | mnt->mnt_master = old; | 247 | mnt->mnt_master = old; |
248 | CLEAR_MNT_SHARED(mnt); | 248 | CLEAR_MNT_SHARED(mnt); |
249 | } else { | 249 | } else if (!(flag & CL_PRIVATE)) { |
250 | if ((flag & CL_PROPAGATION) || IS_MNT_SHARED(old)) | 250 | if ((flag & CL_PROPAGATION) || IS_MNT_SHARED(old)) |
251 | list_add(&mnt->mnt_share, &old->mnt_share); | 251 | list_add(&mnt->mnt_share, &old->mnt_share); |
252 | if (IS_MNT_SLAVE(old)) | 252 | if (IS_MNT_SLAVE(old)) |
@@ -746,6 +746,26 @@ Enomem: | |||
746 | return NULL; | 746 | return NULL; |
747 | } | 747 | } |
748 | 748 | ||
749 | struct vfsmount *collect_mounts(struct vfsmount *mnt, struct dentry *dentry) | ||
750 | { | ||
751 | struct vfsmount *tree; | ||
752 | down_read(&namespace_sem); | ||
753 | tree = copy_tree(mnt, dentry, CL_COPY_ALL | CL_PRIVATE); | ||
754 | up_read(&namespace_sem); | ||
755 | return tree; | ||
756 | } | ||
757 | |||
758 | void drop_collected_mounts(struct vfsmount *mnt) | ||
759 | { | ||
760 | LIST_HEAD(umount_list); | ||
761 | down_read(&namespace_sem); | ||
762 | spin_lock(&vfsmount_lock); | ||
763 | umount_tree(mnt, 0, &umount_list); | ||
764 | spin_unlock(&vfsmount_lock); | ||
765 | up_read(&namespace_sem); | ||
766 | release_mounts(&umount_list); | ||
767 | } | ||
768 | |||
749 | /* | 769 | /* |
750 | * @source_mnt : mount tree to be attached | 770 | * @source_mnt : mount tree to be attached |
751 | * @nd : place the mount tree @source_mnt is attached | 771 | * @nd : place the mount tree @source_mnt is attached |
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c index 97669ed05500..4f80d88e9fee 100644 --- a/fs/nfs/proc.c +++ b/fs/nfs/proc.c | |||
@@ -211,6 +211,7 @@ nfs_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, | |||
211 | nfs_fattr_init(&fattr); | 211 | nfs_fattr_init(&fattr); |
212 | dprintk("NFS call create %s\n", dentry->d_name.name); | 212 | dprintk("NFS call create %s\n", dentry->d_name.name); |
213 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); | 213 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); |
214 | nfs_mark_for_revalidate(dir); | ||
214 | if (status == 0) | 215 | if (status == 0) |
215 | status = nfs_instantiate(dentry, &fhandle, &fattr); | 216 | status = nfs_instantiate(dentry, &fhandle, &fattr); |
216 | dprintk("NFS reply create: %d\n", status); | 217 | dprintk("NFS reply create: %d\n", status); |
diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c index ce558c2e4d53..233ad38161f9 100644 --- a/fs/nfs/unlink.c +++ b/fs/nfs/unlink.c | |||
@@ -171,7 +171,7 @@ static int nfs_call_unlink(struct dentry *dentry, struct nfs_unlinkdata *data) | |||
171 | if (parent == NULL) | 171 | if (parent == NULL) |
172 | goto out_free; | 172 | goto out_free; |
173 | dir = parent->d_inode; | 173 | dir = parent->d_inode; |
174 | if (nfs_copy_dname(dentry, data) == 0) | 174 | if (nfs_copy_dname(dentry, data) != 0) |
175 | goto out_dput; | 175 | goto out_dput; |
176 | /* Non-exclusive lock protects against concurrent lookup() calls */ | 176 | /* Non-exclusive lock protects against concurrent lookup() calls */ |
177 | spin_lock(&dir->i_lock); | 177 | spin_lock(&dir->i_lock); |
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c index 04b266729802..66d0aeb32a47 100644 --- a/fs/nfsd/export.c +++ b/fs/nfsd/export.c | |||
@@ -386,15 +386,13 @@ static int check_export(struct inode *inode, int flags, unsigned char *uuid) | |||
386 | dprintk("exp_export: export of non-dev fs without fsid\n"); | 386 | dprintk("exp_export: export of non-dev fs without fsid\n"); |
387 | return -EINVAL; | 387 | return -EINVAL; |
388 | } | 388 | } |
389 | if (!inode->i_sb->s_export_op) { | 389 | |
390 | if (!inode->i_sb->s_export_op || | ||
391 | !inode->i_sb->s_export_op->fh_to_dentry) { | ||
390 | dprintk("exp_export: export of invalid fs type.\n"); | 392 | dprintk("exp_export: export of invalid fs type.\n"); |
391 | return -EINVAL; | 393 | return -EINVAL; |
392 | } | 394 | } |
393 | 395 | ||
394 | /* Ok, we can export it */; | ||
395 | if (!inode->i_sb->s_export_op->find_exported_dentry) | ||
396 | inode->i_sb->s_export_op->find_exported_dentry = | ||
397 | find_exported_dentry; | ||
398 | return 0; | 396 | return 0; |
399 | 397 | ||
400 | } | 398 | } |
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c index ebd03cc07479..6f03918018a3 100644 --- a/fs/nfsd/nfs4recover.c +++ b/fs/nfsd/nfs4recover.c | |||
@@ -88,7 +88,7 @@ nfs4_make_rec_clidname(char *dname, struct xdr_netobj *clname) | |||
88 | { | 88 | { |
89 | struct xdr_netobj cksum; | 89 | struct xdr_netobj cksum; |
90 | struct hash_desc desc; | 90 | struct hash_desc desc; |
91 | struct scatterlist sg[1]; | 91 | struct scatterlist sg; |
92 | __be32 status = nfserr_resource; | 92 | __be32 status = nfserr_resource; |
93 | 93 | ||
94 | dprintk("NFSD: nfs4_make_rec_clidname for %.*s\n", | 94 | dprintk("NFSD: nfs4_make_rec_clidname for %.*s\n", |
@@ -102,11 +102,9 @@ nfs4_make_rec_clidname(char *dname, struct xdr_netobj *clname) | |||
102 | if (cksum.data == NULL) | 102 | if (cksum.data == NULL) |
103 | goto out; | 103 | goto out; |
104 | 104 | ||
105 | sg[0].page = virt_to_page(clname->data); | 105 | sg_init_one(&sg, clname->data, clname->len); |
106 | sg[0].offset = offset_in_page(clname->data); | ||
107 | sg[0].length = clname->len; | ||
108 | 106 | ||
109 | if (crypto_hash_digest(&desc, sg, sg->length, cksum.data)) | 107 | if (crypto_hash_digest(&desc, &sg, sg.length, cksum.data)) |
110 | goto out; | 108 | goto out; |
111 | 109 | ||
112 | md5_to_hex(dname, cksum.data); | 110 | md5_to_hex(dname, cksum.data); |
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c index 7011d62acfc8..4f712e970584 100644 --- a/fs/nfsd/nfsfh.c +++ b/fs/nfsd/nfsfh.c | |||
@@ -115,8 +115,7 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access) | |||
115 | dprintk("nfsd: fh_verify(%s)\n", SVCFH_fmt(fhp)); | 115 | dprintk("nfsd: fh_verify(%s)\n", SVCFH_fmt(fhp)); |
116 | 116 | ||
117 | if (!fhp->fh_dentry) { | 117 | if (!fhp->fh_dentry) { |
118 | __u32 *datap=NULL; | 118 | struct fid *fid = NULL, sfid; |
119 | __u32 tfh[3]; /* filehandle fragment for oldstyle filehandles */ | ||
120 | int fileid_type; | 119 | int fileid_type; |
121 | int data_left = fh->fh_size/4; | 120 | int data_left = fh->fh_size/4; |
122 | 121 | ||
@@ -128,7 +127,6 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access) | |||
128 | 127 | ||
129 | if (fh->fh_version == 1) { | 128 | if (fh->fh_version == 1) { |
130 | int len; | 129 | int len; |
131 | datap = fh->fh_auth; | ||
132 | if (--data_left<0) goto out; | 130 | if (--data_left<0) goto out; |
133 | switch (fh->fh_auth_type) { | 131 | switch (fh->fh_auth_type) { |
134 | case 0: break; | 132 | case 0: break; |
@@ -144,9 +142,11 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access) | |||
144 | fh->fh_fsid[1] = fh->fh_fsid[2]; | 142 | fh->fh_fsid[1] = fh->fh_fsid[2]; |
145 | } | 143 | } |
146 | if ((data_left -= len)<0) goto out; | 144 | if ((data_left -= len)<0) goto out; |
147 | exp = rqst_exp_find(rqstp, fh->fh_fsid_type, datap); | 145 | exp = rqst_exp_find(rqstp, fh->fh_fsid_type, |
148 | datap += len; | 146 | fh->fh_auth); |
147 | fid = (struct fid *)(fh->fh_auth + len); | ||
149 | } else { | 148 | } else { |
149 | __u32 tfh[2]; | ||
150 | dev_t xdev; | 150 | dev_t xdev; |
151 | ino_t xino; | 151 | ino_t xino; |
152 | if (fh->fh_size != NFS_FHSIZE) | 152 | if (fh->fh_size != NFS_FHSIZE) |
@@ -190,22 +190,22 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access) | |||
190 | error = nfserr_badhandle; | 190 | error = nfserr_badhandle; |
191 | 191 | ||
192 | if (fh->fh_version != 1) { | 192 | if (fh->fh_version != 1) { |
193 | tfh[0] = fh->ofh_ino; | 193 | sfid.i32.ino = fh->ofh_ino; |
194 | tfh[1] = fh->ofh_generation; | 194 | sfid.i32.gen = fh->ofh_generation; |
195 | tfh[2] = fh->ofh_dirino; | 195 | sfid.i32.parent_ino = fh->ofh_dirino; |
196 | datap = tfh; | 196 | fid = &sfid; |
197 | data_left = 3; | 197 | data_left = 3; |
198 | if (fh->ofh_dirino == 0) | 198 | if (fh->ofh_dirino == 0) |
199 | fileid_type = 1; | 199 | fileid_type = FILEID_INO32_GEN; |
200 | else | 200 | else |
201 | fileid_type = 2; | 201 | fileid_type = FILEID_INO32_GEN_PARENT; |
202 | } else | 202 | } else |
203 | fileid_type = fh->fh_fileid_type; | 203 | fileid_type = fh->fh_fileid_type; |
204 | 204 | ||
205 | if (fileid_type == 0) | 205 | if (fileid_type == FILEID_ROOT) |
206 | dentry = dget(exp->ex_dentry); | 206 | dentry = dget(exp->ex_dentry); |
207 | else { | 207 | else { |
208 | dentry = exportfs_decode_fh(exp->ex_mnt, datap, | 208 | dentry = exportfs_decode_fh(exp->ex_mnt, fid, |
209 | data_left, fileid_type, | 209 | data_left, fileid_type, |
210 | nfsd_acceptable, exp); | 210 | nfsd_acceptable, exp); |
211 | } | 211 | } |
@@ -286,16 +286,21 @@ out: | |||
286 | * an inode. In this case a call to fh_update should be made | 286 | * an inode. In this case a call to fh_update should be made |
287 | * before the fh goes out on the wire ... | 287 | * before the fh goes out on the wire ... |
288 | */ | 288 | */ |
289 | static inline int _fh_update(struct dentry *dentry, struct svc_export *exp, | 289 | static void _fh_update(struct svc_fh *fhp, struct svc_export *exp, |
290 | __u32 *datap, int *maxsize) | 290 | struct dentry *dentry) |
291 | { | 291 | { |
292 | if (dentry == exp->ex_dentry) { | 292 | if (dentry != exp->ex_dentry) { |
293 | *maxsize = 0; | 293 | struct fid *fid = (struct fid *) |
294 | return 0; | 294 | (fhp->fh_handle.fh_auth + fhp->fh_handle.fh_size/4 - 1); |
295 | } | 295 | int maxsize = (fhp->fh_maxsize - fhp->fh_handle.fh_size)/4; |
296 | int subtreecheck = !(exp->ex_flags & NFSEXP_NOSUBTREECHECK); | ||
296 | 297 | ||
297 | return exportfs_encode_fh(dentry, datap, maxsize, | 298 | fhp->fh_handle.fh_fileid_type = |
298 | !(exp->ex_flags & NFSEXP_NOSUBTREECHECK)); | 299 | exportfs_encode_fh(dentry, fid, &maxsize, subtreecheck); |
300 | fhp->fh_handle.fh_size += maxsize * 4; | ||
301 | } else { | ||
302 | fhp->fh_handle.fh_fileid_type = FILEID_ROOT; | ||
303 | } | ||
299 | } | 304 | } |
300 | 305 | ||
301 | /* | 306 | /* |
@@ -457,12 +462,8 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, | |||
457 | datap += len/4; | 462 | datap += len/4; |
458 | fhp->fh_handle.fh_size = 4 + len; | 463 | fhp->fh_handle.fh_size = 4 + len; |
459 | 464 | ||
460 | if (inode) { | 465 | if (inode) |
461 | int size = (fhp->fh_maxsize-len-4)/4; | 466 | _fh_update(fhp, exp, dentry); |
462 | fhp->fh_handle.fh_fileid_type = | ||
463 | _fh_update(dentry, exp, datap, &size); | ||
464 | fhp->fh_handle.fh_size += size*4; | ||
465 | } | ||
466 | if (fhp->fh_handle.fh_fileid_type == 255) | 467 | if (fhp->fh_handle.fh_fileid_type == 255) |
467 | return nfserr_opnotsupp; | 468 | return nfserr_opnotsupp; |
468 | } | 469 | } |
@@ -479,7 +480,6 @@ __be32 | |||
479 | fh_update(struct svc_fh *fhp) | 480 | fh_update(struct svc_fh *fhp) |
480 | { | 481 | { |
481 | struct dentry *dentry; | 482 | struct dentry *dentry; |
482 | __u32 *datap; | ||
483 | 483 | ||
484 | if (!fhp->fh_dentry) | 484 | if (!fhp->fh_dentry) |
485 | goto out_bad; | 485 | goto out_bad; |
@@ -490,15 +490,10 @@ fh_update(struct svc_fh *fhp) | |||
490 | if (fhp->fh_handle.fh_version != 1) { | 490 | if (fhp->fh_handle.fh_version != 1) { |
491 | _fh_update_old(dentry, fhp->fh_export, &fhp->fh_handle); | 491 | _fh_update_old(dentry, fhp->fh_export, &fhp->fh_handle); |
492 | } else { | 492 | } else { |
493 | int size; | 493 | if (fhp->fh_handle.fh_fileid_type != FILEID_ROOT) |
494 | if (fhp->fh_handle.fh_fileid_type != 0) | ||
495 | goto out; | 494 | goto out; |
496 | datap = fhp->fh_handle.fh_auth+ | 495 | |
497 | fhp->fh_handle.fh_size/4 -1; | 496 | _fh_update(fhp, fhp->fh_export, dentry); |
498 | size = (fhp->fh_maxsize - fhp->fh_handle.fh_size)/4; | ||
499 | fhp->fh_handle.fh_fileid_type = | ||
500 | _fh_update(dentry, fhp->fh_export, datap, &size); | ||
501 | fhp->fh_handle.fh_size += size*4; | ||
502 | if (fhp->fh_handle.fh_fileid_type == 255) | 497 | if (fhp->fh_handle.fh_fileid_type == 255) |
503 | return nfserr_opnotsupp; | 498 | return nfserr_opnotsupp; |
504 | } | 499 | } |
diff --git a/fs/ntfs/namei.c b/fs/ntfs/namei.c index e93c6142b23c..e1781c8b1650 100644 --- a/fs/ntfs/namei.c +++ b/fs/ntfs/namei.c | |||
@@ -450,58 +450,40 @@ try_next: | |||
450 | return parent_dent; | 450 | return parent_dent; |
451 | } | 451 | } |
452 | 452 | ||
453 | /** | 453 | static struct inode *ntfs_nfs_get_inode(struct super_block *sb, |
454 | * ntfs_get_dentry - find a dentry for the inode from a file handle sub-fragment | 454 | u64 ino, u32 generation) |
455 | * @sb: super block identifying the mounted ntfs volume | ||
456 | * @fh: the file handle sub-fragment | ||
457 | * | ||
458 | * Find a dentry for the inode given a file handle sub-fragment. This function | ||
459 | * is called from fs/exportfs/expfs.c::find_exported_dentry() which in turn is | ||
460 | * called from the default ->decode_fh() which is export_decode_fh() in the | ||
461 | * same file. The code is closely based on the default ->get_dentry() helper | ||
462 | * fs/exportfs/expfs.c::get_object(). | ||
463 | * | ||
464 | * The @fh contains two 32-bit unsigned values, the first one is the inode | ||
465 | * number and the second one is the inode generation. | ||
466 | * | ||
467 | * Return the dentry on success or the error code on error (IS_ERR() is true). | ||
468 | */ | ||
469 | static struct dentry *ntfs_get_dentry(struct super_block *sb, void *fh) | ||
470 | { | 455 | { |
471 | struct inode *vi; | 456 | struct inode *inode; |
472 | struct dentry *dent; | ||
473 | unsigned long ino = ((u32 *)fh)[0]; | ||
474 | u32 gen = ((u32 *)fh)[1]; | ||
475 | 457 | ||
476 | ntfs_debug("Entering for inode 0x%lx, generation 0x%x.", ino, gen); | 458 | inode = ntfs_iget(sb, ino); |
477 | vi = ntfs_iget(sb, ino); | 459 | if (!IS_ERR(inode)) { |
478 | if (IS_ERR(vi)) { | 460 | if (is_bad_inode(inode) || inode->i_generation != generation) { |
479 | ntfs_error(sb, "Failed to get inode 0x%lx.", ino); | 461 | iput(inode); |
480 | return (struct dentry *)vi; | 462 | inode = ERR_PTR(-ESTALE); |
481 | } | 463 | } |
482 | if (unlikely(is_bad_inode(vi) || vi->i_generation != gen)) { | ||
483 | /* We didn't find the right inode. */ | ||
484 | ntfs_error(sb, "Inode 0x%lx, bad count: %d %d or version 0x%x " | ||
485 | "0x%x.", vi->i_ino, vi->i_nlink, | ||
486 | atomic_read(&vi->i_count), vi->i_generation, | ||
487 | gen); | ||
488 | iput(vi); | ||
489 | return ERR_PTR(-ESTALE); | ||
490 | } | ||
491 | /* Now find a dentry. If possible, get a well-connected one. */ | ||
492 | dent = d_alloc_anon(vi); | ||
493 | if (unlikely(!dent)) { | ||
494 | iput(vi); | ||
495 | return ERR_PTR(-ENOMEM); | ||
496 | } | 464 | } |
497 | ntfs_debug("Done for inode 0x%lx, generation 0x%x.", ino, gen); | 465 | |
498 | return dent; | 466 | return inode; |
467 | } | ||
468 | |||
469 | static struct dentry *ntfs_fh_to_dentry(struct super_block *sb, struct fid *fid, | ||
470 | int fh_len, int fh_type) | ||
471 | { | ||
472 | return generic_fh_to_dentry(sb, fid, fh_len, fh_type, | ||
473 | ntfs_nfs_get_inode); | ||
474 | } | ||
475 | |||
476 | static struct dentry *ntfs_fh_to_parent(struct super_block *sb, struct fid *fid, | ||
477 | int fh_len, int fh_type) | ||
478 | { | ||
479 | return generic_fh_to_parent(sb, fid, fh_len, fh_type, | ||
480 | ntfs_nfs_get_inode); | ||
499 | } | 481 | } |
500 | 482 | ||
501 | /** | 483 | /** |
502 | * Export operations allowing NFS exporting of mounted NTFS partitions. | 484 | * Export operations allowing NFS exporting of mounted NTFS partitions. |
503 | * | 485 | * |
504 | * We use the default ->decode_fh() and ->encode_fh() for now. Note that they | 486 | * We use the default ->encode_fh() for now. Note that they |
505 | * use 32 bits to store the inode number which is an unsigned long so on 64-bit | 487 | * use 32 bits to store the inode number which is an unsigned long so on 64-bit |
506 | * architectures is usually 64 bits so it would all fail horribly on huge | 488 | * architectures is usually 64 bits so it would all fail horribly on huge |
507 | * volumes. I guess we need to define our own encode and decode fh functions | 489 | * volumes. I guess we need to define our own encode and decode fh functions |
@@ -517,10 +499,9 @@ static struct dentry *ntfs_get_dentry(struct super_block *sb, void *fh) | |||
517 | * allowing the inode number 0 which is used in NTFS for the system file $MFT | 499 | * allowing the inode number 0 which is used in NTFS for the system file $MFT |
518 | * and due to using iget() whereas NTFS needs ntfs_iget(). | 500 | * and due to using iget() whereas NTFS needs ntfs_iget(). |
519 | */ | 501 | */ |
520 | struct export_operations ntfs_export_ops = { | 502 | const struct export_operations ntfs_export_ops = { |
521 | .get_parent = ntfs_get_parent, /* Find the parent of a given | 503 | .get_parent = ntfs_get_parent, /* Find the parent of a given |
522 | directory. */ | 504 | directory. */ |
523 | .get_dentry = ntfs_get_dentry, /* Find a dentry for the inode | 505 | .fh_to_dentry = ntfs_fh_to_dentry, |
524 | given a file handle | 506 | .fh_to_parent = ntfs_fh_to_parent, |
525 | sub-fragment. */ | ||
526 | }; | 507 | }; |
diff --git a/fs/ntfs/ntfs.h b/fs/ntfs/ntfs.h index d73f5a9ac341..d6a340bf80fc 100644 --- a/fs/ntfs/ntfs.h +++ b/fs/ntfs/ntfs.h | |||
@@ -69,7 +69,7 @@ extern const struct inode_operations ntfs_dir_inode_ops; | |||
69 | extern const struct file_operations ntfs_empty_file_ops; | 69 | extern const struct file_operations ntfs_empty_file_ops; |
70 | extern const struct inode_operations ntfs_empty_inode_ops; | 70 | extern const struct inode_operations ntfs_empty_inode_ops; |
71 | 71 | ||
72 | extern struct export_operations ntfs_export_ops; | 72 | extern const struct export_operations ntfs_export_ops; |
73 | 73 | ||
74 | /** | 74 | /** |
75 | * NTFS_SB - return the ntfs volume given a vfs super block | 75 | * NTFS_SB - return the ntfs volume given a vfs super block |
diff --git a/fs/ocfs2/export.c b/fs/ocfs2/export.c index c3bbc198f9ce..535bfa9568a4 100644 --- a/fs/ocfs2/export.c +++ b/fs/ocfs2/export.c | |||
@@ -45,9 +45,9 @@ struct ocfs2_inode_handle | |||
45 | u32 ih_generation; | 45 | u32 ih_generation; |
46 | }; | 46 | }; |
47 | 47 | ||
48 | static struct dentry *ocfs2_get_dentry(struct super_block *sb, void *vobjp) | 48 | static struct dentry *ocfs2_get_dentry(struct super_block *sb, |
49 | struct ocfs2_inode_handle *handle) | ||
49 | { | 50 | { |
50 | struct ocfs2_inode_handle *handle = vobjp; | ||
51 | struct inode *inode; | 51 | struct inode *inode; |
52 | struct dentry *result; | 52 | struct dentry *result; |
53 | 53 | ||
@@ -194,54 +194,37 @@ bail: | |||
194 | return type; | 194 | return type; |
195 | } | 195 | } |
196 | 196 | ||
197 | static struct dentry *ocfs2_decode_fh(struct super_block *sb, u32 *fh_in, | 197 | static struct dentry *ocfs2_fh_to_dentry(struct super_block *sb, |
198 | int fh_len, int fileid_type, | 198 | struct fid *fid, int fh_len, int fh_type) |
199 | int (*acceptable)(void *context, | ||
200 | struct dentry *de), | ||
201 | void *context) | ||
202 | { | 199 | { |
203 | struct ocfs2_inode_handle handle, parent; | 200 | struct ocfs2_inode_handle handle; |
204 | struct dentry *ret = NULL; | ||
205 | __le32 *fh = (__force __le32 *) fh_in; | ||
206 | |||
207 | mlog_entry("(0x%p, 0x%p, %d, %d, 0x%p, 0x%p)\n", | ||
208 | sb, fh, fh_len, fileid_type, acceptable, context); | ||
209 | |||
210 | if (fh_len < 3 || fileid_type > 2) | ||
211 | goto bail; | ||
212 | |||
213 | if (fileid_type == 2) { | ||
214 | if (fh_len < 6) | ||
215 | goto bail; | ||
216 | |||
217 | parent.ih_blkno = (u64)le32_to_cpu(fh[3]) << 32; | ||
218 | parent.ih_blkno |= (u64)le32_to_cpu(fh[4]); | ||
219 | parent.ih_generation = le32_to_cpu(fh[5]); | ||
220 | 201 | ||
221 | mlog(0, "Decoding parent: blkno: %llu, generation: %u\n", | 202 | if (fh_len < 3 || fh_type > 2) |
222 | (unsigned long long)parent.ih_blkno, | 203 | return NULL; |
223 | parent.ih_generation); | ||
224 | } | ||
225 | 204 | ||
226 | handle.ih_blkno = (u64)le32_to_cpu(fh[0]) << 32; | 205 | handle.ih_blkno = (u64)le32_to_cpu(fid->raw[0]) << 32; |
227 | handle.ih_blkno |= (u64)le32_to_cpu(fh[1]); | 206 | handle.ih_blkno |= (u64)le32_to_cpu(fid->raw[1]); |
228 | handle.ih_generation = le32_to_cpu(fh[2]); | 207 | handle.ih_generation = le32_to_cpu(fid->raw[2]); |
208 | return ocfs2_get_dentry(sb, &handle); | ||
209 | } | ||
229 | 210 | ||
230 | mlog(0, "Encoding fh: blkno: %llu, generation: %u\n", | 211 | static struct dentry *ocfs2_fh_to_parent(struct super_block *sb, |
231 | (unsigned long long)handle.ih_blkno, handle.ih_generation); | 212 | struct fid *fid, int fh_len, int fh_type) |
213 | { | ||
214 | struct ocfs2_inode_handle parent; | ||
232 | 215 | ||
233 | ret = ocfs2_export_ops.find_exported_dentry(sb, &handle, &parent, | 216 | if (fh_type != 2 || fh_len < 6) |
234 | acceptable, context); | 217 | return NULL; |
235 | 218 | ||
236 | bail: | 219 | parent.ih_blkno = (u64)le32_to_cpu(fid->raw[3]) << 32; |
237 | mlog_exit_ptr(ret); | 220 | parent.ih_blkno |= (u64)le32_to_cpu(fid->raw[4]); |
238 | return ret; | 221 | parent.ih_generation = le32_to_cpu(fid->raw[5]); |
222 | return ocfs2_get_dentry(sb, &parent); | ||
239 | } | 223 | } |
240 | 224 | ||
241 | struct export_operations ocfs2_export_ops = { | 225 | const struct export_operations ocfs2_export_ops = { |
242 | .decode_fh = ocfs2_decode_fh, | ||
243 | .encode_fh = ocfs2_encode_fh, | 226 | .encode_fh = ocfs2_encode_fh, |
244 | 227 | .fh_to_dentry = ocfs2_fh_to_dentry, | |
228 | .fh_to_parent = ocfs2_fh_to_parent, | ||
245 | .get_parent = ocfs2_get_parent, | 229 | .get_parent = ocfs2_get_parent, |
246 | .get_dentry = ocfs2_get_dentry, | ||
247 | }; | 230 | }; |
diff --git a/fs/ocfs2/export.h b/fs/ocfs2/export.h index e08bed9e45a0..41a738678c37 100644 --- a/fs/ocfs2/export.h +++ b/fs/ocfs2/export.h | |||
@@ -28,6 +28,6 @@ | |||
28 | 28 | ||
29 | #include <linux/exportfs.h> | 29 | #include <linux/exportfs.h> |
30 | 30 | ||
31 | extern struct export_operations ocfs2_export_ops; | 31 | extern const struct export_operations ocfs2_export_ops; |
32 | 32 | ||
33 | #endif /* OCFS2_EXPORT_H */ | 33 | #endif /* OCFS2_EXPORT_H */ |
@@ -569,7 +569,7 @@ asmlinkage long sys_fchmod(unsigned int fd, mode_t mode) | |||
569 | dentry = file->f_path.dentry; | 569 | dentry = file->f_path.dentry; |
570 | inode = dentry->d_inode; | 570 | inode = dentry->d_inode; |
571 | 571 | ||
572 | audit_inode(NULL, inode); | 572 | audit_inode(NULL, dentry); |
573 | 573 | ||
574 | err = -EROFS; | 574 | err = -EROFS; |
575 | if (IS_RDONLY(inode)) | 575 | if (IS_RDONLY(inode)) |
@@ -727,7 +727,7 @@ asmlinkage long sys_fchown(unsigned int fd, uid_t user, gid_t group) | |||
727 | goto out; | 727 | goto out; |
728 | 728 | ||
729 | dentry = file->f_path.dentry; | 729 | dentry = file->f_path.dentry; |
730 | audit_inode(NULL, dentry->d_inode); | 730 | audit_inode(NULL, dentry); |
731 | error = chown_common(dentry, user, group); | 731 | error = chown_common(dentry, user, group); |
732 | fput(file); | 732 | fput(file); |
733 | out: | 733 | out: |
diff --git a/fs/pnode.h b/fs/pnode.h index d45bd8ec36bf..f249be2fee7a 100644 --- a/fs/pnode.h +++ b/fs/pnode.h | |||
@@ -22,6 +22,7 @@ | |||
22 | #define CL_COPY_ALL 0x04 | 22 | #define CL_COPY_ALL 0x04 |
23 | #define CL_MAKE_SHARED 0x08 | 23 | #define CL_MAKE_SHARED 0x08 |
24 | #define CL_PROPAGATION 0x10 | 24 | #define CL_PROPAGATION 0x10 |
25 | #define CL_PRIVATE 0x20 | ||
25 | 26 | ||
26 | static inline void set_mnt_shared(struct vfsmount *mnt) | 27 | static inline void set_mnt_shared(struct vfsmount *mnt) |
27 | { | 28 | { |
diff --git a/fs/proc/base.c b/fs/proc/base.c index 39a3d7c969c5..aeaf0d0f2f51 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
@@ -2255,27 +2255,6 @@ static const struct inode_operations proc_tgid_base_inode_operations = { | |||
2255 | .setattr = proc_setattr, | 2255 | .setattr = proc_setattr, |
2256 | }; | 2256 | }; |
2257 | 2257 | ||
2258 | /** | ||
2259 | * proc_flush_task - Remove dcache entries for @task from the /proc dcache. | ||
2260 | * | ||
2261 | * @task: task that should be flushed. | ||
2262 | * | ||
2263 | * Looks in the dcache for | ||
2264 | * /proc/@pid | ||
2265 | * /proc/@tgid/task/@pid | ||
2266 | * if either directory is present flushes it and all of it'ts children | ||
2267 | * from the dcache. | ||
2268 | * | ||
2269 | * It is safe and reasonable to cache /proc entries for a task until | ||
2270 | * that task exits. After that they just clog up the dcache with | ||
2271 | * useless entries, possibly causing useful dcache entries to be | ||
2272 | * flushed instead. This routine is proved to flush those useless | ||
2273 | * dcache entries at process exit time. | ||
2274 | * | ||
2275 | * NOTE: This routine is just an optimization so it does not guarantee | ||
2276 | * that no dcache entries will exist at process exit time it | ||
2277 | * just makes it very unlikely that any will persist. | ||
2278 | */ | ||
2279 | static void proc_flush_task_mnt(struct vfsmount *mnt, pid_t pid, pid_t tgid) | 2258 | static void proc_flush_task_mnt(struct vfsmount *mnt, pid_t pid, pid_t tgid) |
2280 | { | 2259 | { |
2281 | struct dentry *dentry, *leader, *dir; | 2260 | struct dentry *dentry, *leader, *dir; |
@@ -2322,10 +2301,29 @@ out: | |||
2322 | return; | 2301 | return; |
2323 | } | 2302 | } |
2324 | 2303 | ||
2325 | /* | 2304 | /** |
2326 | * when flushing dentries from proc one need to flush them from global | 2305 | * proc_flush_task - Remove dcache entries for @task from the /proc dcache. |
2306 | * @task: task that should be flushed. | ||
2307 | * | ||
2308 | * When flushing dentries from proc, one needs to flush them from global | ||
2327 | * proc (proc_mnt) and from all the namespaces' procs this task was seen | 2309 | * proc (proc_mnt) and from all the namespaces' procs this task was seen |
2328 | * in. this call is supposed to make all this job. | 2310 | * in. This call is supposed to do all of this job. |
2311 | * | ||
2312 | * Looks in the dcache for | ||
2313 | * /proc/@pid | ||
2314 | * /proc/@tgid/task/@pid | ||
2315 | * if either directory is present flushes it and all of it'ts children | ||
2316 | * from the dcache. | ||
2317 | * | ||
2318 | * It is safe and reasonable to cache /proc entries for a task until | ||
2319 | * that task exits. After that they just clog up the dcache with | ||
2320 | * useless entries, possibly causing useful dcache entries to be | ||
2321 | * flushed instead. This routine is proved to flush those useless | ||
2322 | * dcache entries at process exit time. | ||
2323 | * | ||
2324 | * NOTE: This routine is just an optimization so it does not guarantee | ||
2325 | * that no dcache entries will exist at process exit time it | ||
2326 | * just makes it very unlikely that any will persist. | ||
2329 | */ | 2327 | */ |
2330 | 2328 | ||
2331 | void proc_flush_task(struct task_struct *task) | 2329 | void proc_flush_task(struct task_struct *task) |
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c index a991af96f3f0..231fd5ccadc5 100644 --- a/fs/reiserfs/inode.c +++ b/fs/reiserfs/inode.c | |||
@@ -1515,19 +1515,20 @@ struct inode *reiserfs_iget(struct super_block *s, const struct cpu_key *key) | |||
1515 | return inode; | 1515 | return inode; |
1516 | } | 1516 | } |
1517 | 1517 | ||
1518 | struct dentry *reiserfs_get_dentry(struct super_block *sb, void *vobjp) | 1518 | static struct dentry *reiserfs_get_dentry(struct super_block *sb, |
1519 | u32 objectid, u32 dir_id, u32 generation) | ||
1520 | |||
1519 | { | 1521 | { |
1520 | __u32 *data = vobjp; | ||
1521 | struct cpu_key key; | 1522 | struct cpu_key key; |
1522 | struct dentry *result; | 1523 | struct dentry *result; |
1523 | struct inode *inode; | 1524 | struct inode *inode; |
1524 | 1525 | ||
1525 | key.on_disk_key.k_objectid = data[0]; | 1526 | key.on_disk_key.k_objectid = objectid; |
1526 | key.on_disk_key.k_dir_id = data[1]; | 1527 | key.on_disk_key.k_dir_id = dir_id; |
1527 | reiserfs_write_lock(sb); | 1528 | reiserfs_write_lock(sb); |
1528 | inode = reiserfs_iget(sb, &key); | 1529 | inode = reiserfs_iget(sb, &key); |
1529 | if (inode && !IS_ERR(inode) && data[2] != 0 && | 1530 | if (inode && !IS_ERR(inode) && generation != 0 && |
1530 | data[2] != inode->i_generation) { | 1531 | generation != inode->i_generation) { |
1531 | iput(inode); | 1532 | iput(inode); |
1532 | inode = NULL; | 1533 | inode = NULL; |
1533 | } | 1534 | } |
@@ -1544,14 +1545,9 @@ struct dentry *reiserfs_get_dentry(struct super_block *sb, void *vobjp) | |||
1544 | return result; | 1545 | return result; |
1545 | } | 1546 | } |
1546 | 1547 | ||
1547 | struct dentry *reiserfs_decode_fh(struct super_block *sb, __u32 * data, | 1548 | struct dentry *reiserfs_fh_to_dentry(struct super_block *sb, struct fid *fid, |
1548 | int len, int fhtype, | 1549 | int fh_len, int fh_type) |
1549 | int (*acceptable) (void *contect, | ||
1550 | struct dentry * de), | ||
1551 | void *context) | ||
1552 | { | 1550 | { |
1553 | __u32 obj[3], parent[3]; | ||
1554 | |||
1555 | /* fhtype happens to reflect the number of u32s encoded. | 1551 | /* fhtype happens to reflect the number of u32s encoded. |
1556 | * due to a bug in earlier code, fhtype might indicate there | 1552 | * due to a bug in earlier code, fhtype might indicate there |
1557 | * are more u32s then actually fitted. | 1553 | * are more u32s then actually fitted. |
@@ -1564,32 +1560,28 @@ struct dentry *reiserfs_decode_fh(struct super_block *sb, __u32 * data, | |||
1564 | * 6 - as above plus generation of directory | 1560 | * 6 - as above plus generation of directory |
1565 | * 6 does not fit in NFSv2 handles | 1561 | * 6 does not fit in NFSv2 handles |
1566 | */ | 1562 | */ |
1567 | if (fhtype > len) { | 1563 | if (fh_type > fh_len) { |
1568 | if (fhtype != 6 || len != 5) | 1564 | if (fh_type != 6 || fh_len != 5) |
1569 | reiserfs_warning(sb, | 1565 | reiserfs_warning(sb, |
1570 | "nfsd/reiserfs, fhtype=%d, len=%d - odd", | 1566 | "nfsd/reiserfs, fhtype=%d, len=%d - odd", |
1571 | fhtype, len); | 1567 | fh_type, fh_len); |
1572 | fhtype = 5; | 1568 | fh_type = 5; |
1573 | } | 1569 | } |
1574 | 1570 | ||
1575 | obj[0] = data[0]; | 1571 | return reiserfs_get_dentry(sb, fid->raw[0], fid->raw[1], |
1576 | obj[1] = data[1]; | 1572 | (fh_type == 3 || fh_type >= 5) ? fid->raw[2] : 0); |
1577 | if (fhtype == 3 || fhtype >= 5) | 1573 | } |
1578 | obj[2] = data[2]; | ||
1579 | else | ||
1580 | obj[2] = 0; /* generation number */ | ||
1581 | 1574 | ||
1582 | if (fhtype >= 4) { | 1575 | struct dentry *reiserfs_fh_to_parent(struct super_block *sb, struct fid *fid, |
1583 | parent[0] = data[fhtype >= 5 ? 3 : 2]; | 1576 | int fh_len, int fh_type) |
1584 | parent[1] = data[fhtype >= 5 ? 4 : 3]; | 1577 | { |
1585 | if (fhtype == 6) | 1578 | if (fh_type < 4) |
1586 | parent[2] = data[5]; | 1579 | return NULL; |
1587 | else | 1580 | |
1588 | parent[2] = 0; | 1581 | return reiserfs_get_dentry(sb, |
1589 | } | 1582 | (fh_type >= 5) ? fid->raw[3] : fid->raw[2], |
1590 | return sb->s_export_op->find_exported_dentry(sb, obj, | 1583 | (fh_type >= 5) ? fid->raw[4] : fid->raw[3], |
1591 | fhtype < 4 ? NULL : parent, | 1584 | (fh_type == 6) ? fid->raw[5] : 0); |
1592 | acceptable, context); | ||
1593 | } | 1585 | } |
1594 | 1586 | ||
1595 | int reiserfs_encode_fh(struct dentry *dentry, __u32 * data, int *lenp, | 1587 | int reiserfs_encode_fh(struct dentry *dentry, __u32 * data, int *lenp, |
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index 98c3781bc069..5cd85fe5df5d 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c | |||
@@ -661,11 +661,11 @@ static struct quotactl_ops reiserfs_qctl_operations = { | |||
661 | }; | 661 | }; |
662 | #endif | 662 | #endif |
663 | 663 | ||
664 | static struct export_operations reiserfs_export_ops = { | 664 | static const struct export_operations reiserfs_export_ops = { |
665 | .encode_fh = reiserfs_encode_fh, | 665 | .encode_fh = reiserfs_encode_fh, |
666 | .decode_fh = reiserfs_decode_fh, | 666 | .fh_to_dentry = reiserfs_fh_to_dentry, |
667 | .fh_to_parent = reiserfs_fh_to_parent, | ||
667 | .get_parent = reiserfs_get_parent, | 668 | .get_parent = reiserfs_get_parent, |
668 | .get_dentry = reiserfs_get_dentry, | ||
669 | }; | 669 | }; |
670 | 670 | ||
671 | /* this struct is used in reiserfs_getopt () for containing the value for those | 671 | /* this struct is used in reiserfs_getopt () for containing the value for those |
diff --git a/fs/xattr.c b/fs/xattr.c index a44fd92caca3..6645b7313b33 100644 --- a/fs/xattr.c +++ b/fs/xattr.c | |||
@@ -267,7 +267,7 @@ sys_fsetxattr(int fd, char __user *name, void __user *value, | |||
267 | if (!f) | 267 | if (!f) |
268 | return error; | 268 | return error; |
269 | dentry = f->f_path.dentry; | 269 | dentry = f->f_path.dentry; |
270 | audit_inode(NULL, dentry->d_inode); | 270 | audit_inode(NULL, dentry); |
271 | error = setxattr(dentry, name, value, size, flags); | 271 | error = setxattr(dentry, name, value, size, flags); |
272 | fput(f); | 272 | fput(f); |
273 | return error; | 273 | return error; |
@@ -349,7 +349,7 @@ sys_fgetxattr(int fd, char __user *name, void __user *value, size_t size) | |||
349 | f = fget(fd); | 349 | f = fget(fd); |
350 | if (!f) | 350 | if (!f) |
351 | return error; | 351 | return error; |
352 | audit_inode(NULL, f->f_path.dentry->d_inode); | 352 | audit_inode(NULL, f->f_path.dentry); |
353 | error = getxattr(f->f_path.dentry, name, value, size); | 353 | error = getxattr(f->f_path.dentry, name, value, size); |
354 | fput(f); | 354 | fput(f); |
355 | return error; | 355 | return error; |
@@ -422,7 +422,7 @@ sys_flistxattr(int fd, char __user *list, size_t size) | |||
422 | f = fget(fd); | 422 | f = fget(fd); |
423 | if (!f) | 423 | if (!f) |
424 | return error; | 424 | return error; |
425 | audit_inode(NULL, f->f_path.dentry->d_inode); | 425 | audit_inode(NULL, f->f_path.dentry); |
426 | error = listxattr(f->f_path.dentry, list, size); | 426 | error = listxattr(f->f_path.dentry, list, size); |
427 | fput(f); | 427 | fput(f); |
428 | return error; | 428 | return error; |
@@ -485,7 +485,7 @@ sys_fremovexattr(int fd, char __user *name) | |||
485 | if (!f) | 485 | if (!f) |
486 | return error; | 486 | return error; |
487 | dentry = f->f_path.dentry; | 487 | dentry = f->f_path.dentry; |
488 | audit_inode(NULL, dentry->d_inode); | 488 | audit_inode(NULL, dentry); |
489 | error = removexattr(dentry, name); | 489 | error = removexattr(dentry, name); |
490 | fput(f); | 490 | fput(f); |
491 | return error; | 491 | return error; |
diff --git a/fs/xfs/linux-2.6/xfs_export.c b/fs/xfs/linux-2.6/xfs_export.c index 3586c7a28d2c..15bd4948832c 100644 --- a/fs/xfs/linux-2.6/xfs_export.c +++ b/fs/xfs/linux-2.6/xfs_export.c | |||
@@ -33,62 +33,25 @@ | |||
33 | static struct dentry dotdot = { .d_name.name = "..", .d_name.len = 2, }; | 33 | static struct dentry dotdot = { .d_name.name = "..", .d_name.len = 2, }; |
34 | 34 | ||
35 | /* | 35 | /* |
36 | * XFS encodes and decodes the fileid portion of NFS filehandles | 36 | * Note that we only accept fileids which are long enough rather than allow |
37 | * itself instead of letting the generic NFS code do it. This | 37 | * the parent generation number to default to zero. XFS considers zero a |
38 | * allows filesystems with 64 bit inode numbers to be exported. | 38 | * valid generation number not an invalid/wildcard value. |
39 | * | ||
40 | * Note that a side effect is that xfs_vget() won't be passed a | ||
41 | * zero inode/generation pair under normal circumstances. As | ||
42 | * however a malicious client could send us such data, the check | ||
43 | * remains in that code. | ||
44 | */ | 39 | */ |
45 | 40 | static int xfs_fileid_length(int fileid_type) | |
46 | STATIC struct dentry * | ||
47 | xfs_fs_decode_fh( | ||
48 | struct super_block *sb, | ||
49 | __u32 *fh, | ||
50 | int fh_len, | ||
51 | int fileid_type, | ||
52 | int (*acceptable)( | ||
53 | void *context, | ||
54 | struct dentry *de), | ||
55 | void *context) | ||
56 | { | 41 | { |
57 | xfs_fid_t ifid; | 42 | switch (fileid_type) { |
58 | xfs_fid_t pfid; | 43 | case FILEID_INO32_GEN: |
59 | void *parent = NULL; | 44 | return 2; |
60 | int is64 = 0; | 45 | case FILEID_INO32_GEN_PARENT: |
61 | __u32 *p = fh; | 46 | return 4; |
62 | 47 | case FILEID_INO32_GEN | XFS_FILEID_TYPE_64FLAG: | |
63 | #if XFS_BIG_INUMS | 48 | return 3; |
64 | is64 = (fileid_type & XFS_FILEID_TYPE_64FLAG); | 49 | case FILEID_INO32_GEN_PARENT | XFS_FILEID_TYPE_64FLAG: |
65 | fileid_type &= ~XFS_FILEID_TYPE_64FLAG; | 50 | return 6; |
66 | #endif | ||
67 | |||
68 | /* | ||
69 | * Note that we only accept fileids which are long enough | ||
70 | * rather than allow the parent generation number to default | ||
71 | * to zero. XFS considers zero a valid generation number not | ||
72 | * an invalid/wildcard value. There's little point printk'ing | ||
73 | * a warning here as we don't have the client information | ||
74 | * which would make such a warning useful. | ||
75 | */ | ||
76 | if (fileid_type > 2 || | ||
77 | fh_len < xfs_fileid_length((fileid_type == 2), is64)) | ||
78 | return NULL; | ||
79 | |||
80 | p = xfs_fileid_decode_fid2(p, &ifid, is64); | ||
81 | |||
82 | if (fileid_type == 2) { | ||
83 | p = xfs_fileid_decode_fid2(p, &pfid, is64); | ||
84 | parent = &pfid; | ||
85 | } | 51 | } |
86 | 52 | return 255; /* invalid */ | |
87 | fh = (__u32 *)&ifid; | ||
88 | return sb->s_export_op->find_exported_dentry(sb, fh, parent, acceptable, context); | ||
89 | } | 53 | } |
90 | 54 | ||
91 | |||
92 | STATIC int | 55 | STATIC int |
93 | xfs_fs_encode_fh( | 56 | xfs_fs_encode_fh( |
94 | struct dentry *dentry, | 57 | struct dentry *dentry, |
@@ -96,21 +59,21 @@ xfs_fs_encode_fh( | |||
96 | int *max_len, | 59 | int *max_len, |
97 | int connectable) | 60 | int connectable) |
98 | { | 61 | { |
62 | struct fid *fid = (struct fid *)fh; | ||
63 | struct xfs_fid64 *fid64 = (struct xfs_fid64 *)fh; | ||
99 | struct inode *inode = dentry->d_inode; | 64 | struct inode *inode = dentry->d_inode; |
100 | int type = 1; | 65 | int fileid_type; |
101 | __u32 *p = fh; | ||
102 | int len; | 66 | int len; |
103 | int is64 = 0; | ||
104 | #if XFS_BIG_INUMS | ||
105 | if (!(XFS_M(inode->i_sb)->m_flags & XFS_MOUNT_SMALL_INUMS)) { | ||
106 | /* filesystem may contain 64bit inode numbers */ | ||
107 | is64 = XFS_FILEID_TYPE_64FLAG; | ||
108 | } | ||
109 | #endif | ||
110 | 67 | ||
111 | /* Directories don't need their parent encoded, they have ".." */ | 68 | /* Directories don't need their parent encoded, they have ".." */ |
112 | if (S_ISDIR(inode->i_mode)) | 69 | if (S_ISDIR(inode->i_mode)) |
113 | connectable = 0; | 70 | fileid_type = FILEID_INO32_GEN; |
71 | else | ||
72 | fileid_type = FILEID_INO32_GEN_PARENT; | ||
73 | |||
74 | /* filesystem may contain 64bit inode numbers */ | ||
75 | if (!(XFS_M(inode->i_sb)->m_flags & XFS_MOUNT_SMALL_INUMS)) | ||
76 | fileid_type |= XFS_FILEID_TYPE_64FLAG; | ||
114 | 77 | ||
115 | /* | 78 | /* |
116 | * Only encode if there is enough space given. In practice | 79 | * Only encode if there is enough space given. In practice |
@@ -118,39 +81,118 @@ xfs_fs_encode_fh( | |||
118 | * over NFSv2 with the subtree_check export option; the other | 81 | * over NFSv2 with the subtree_check export option; the other |
119 | * seven combinations work. The real answer is "don't use v2". | 82 | * seven combinations work. The real answer is "don't use v2". |
120 | */ | 83 | */ |
121 | len = xfs_fileid_length(connectable, is64); | 84 | len = xfs_fileid_length(fileid_type); |
122 | if (*max_len < len) | 85 | if (*max_len < len) |
123 | return 255; | 86 | return 255; |
124 | *max_len = len; | 87 | *max_len = len; |
125 | 88 | ||
126 | p = xfs_fileid_encode_inode(p, inode, is64); | 89 | switch (fileid_type) { |
127 | if (connectable) { | 90 | case FILEID_INO32_GEN_PARENT: |
128 | spin_lock(&dentry->d_lock); | 91 | spin_lock(&dentry->d_lock); |
129 | p = xfs_fileid_encode_inode(p, dentry->d_parent->d_inode, is64); | 92 | fid->i32.parent_ino = dentry->d_parent->d_inode->i_ino; |
93 | fid->i32.parent_gen = dentry->d_parent->d_inode->i_generation; | ||
130 | spin_unlock(&dentry->d_lock); | 94 | spin_unlock(&dentry->d_lock); |
131 | type = 2; | 95 | /*FALLTHRU*/ |
96 | case FILEID_INO32_GEN: | ||
97 | fid->i32.ino = inode->i_ino; | ||
98 | fid->i32.gen = inode->i_generation; | ||
99 | break; | ||
100 | case FILEID_INO32_GEN_PARENT | XFS_FILEID_TYPE_64FLAG: | ||
101 | spin_lock(&dentry->d_lock); | ||
102 | fid64->parent_ino = dentry->d_parent->d_inode->i_ino; | ||
103 | fid64->parent_gen = dentry->d_parent->d_inode->i_generation; | ||
104 | spin_unlock(&dentry->d_lock); | ||
105 | /*FALLTHRU*/ | ||
106 | case FILEID_INO32_GEN | XFS_FILEID_TYPE_64FLAG: | ||
107 | fid64->ino = inode->i_ino; | ||
108 | fid64->gen = inode->i_generation; | ||
109 | break; | ||
132 | } | 110 | } |
133 | BUG_ON((p - fh) != len); | 111 | |
134 | return type | is64; | 112 | return fileid_type; |
135 | } | 113 | } |
136 | 114 | ||
137 | STATIC struct dentry * | 115 | STATIC struct inode * |
138 | xfs_fs_get_dentry( | 116 | xfs_nfs_get_inode( |
139 | struct super_block *sb, | 117 | struct super_block *sb, |
140 | void *data) | 118 | u64 ino, |
141 | { | 119 | u32 generation) |
120 | { | ||
121 | xfs_fid_t xfid; | ||
142 | bhv_vnode_t *vp; | 122 | bhv_vnode_t *vp; |
143 | struct inode *inode; | ||
144 | struct dentry *result; | ||
145 | int error; | 123 | int error; |
146 | 124 | ||
147 | error = xfs_vget(XFS_M(sb), &vp, data); | 125 | xfid.fid_len = sizeof(xfs_fid_t) - sizeof(xfid.fid_len); |
148 | if (error || vp == NULL) | 126 | xfid.fid_pad = 0; |
149 | return ERR_PTR(-ESTALE) ; | 127 | xfid.fid_ino = ino; |
128 | xfid.fid_gen = generation; | ||
150 | 129 | ||
151 | inode = vn_to_inode(vp); | 130 | error = xfs_vget(XFS_M(sb), &vp, &xfid); |
131 | if (error) | ||
132 | return ERR_PTR(-error); | ||
133 | |||
134 | return vp ? vn_to_inode(vp) : NULL; | ||
135 | } | ||
136 | |||
137 | STATIC struct dentry * | ||
138 | xfs_fs_fh_to_dentry(struct super_block *sb, struct fid *fid, | ||
139 | int fh_len, int fileid_type) | ||
140 | { | ||
141 | struct xfs_fid64 *fid64 = (struct xfs_fid64 *)fid; | ||
142 | struct inode *inode = NULL; | ||
143 | struct dentry *result; | ||
144 | |||
145 | if (fh_len < xfs_fileid_length(fileid_type)) | ||
146 | return NULL; | ||
147 | |||
148 | switch (fileid_type) { | ||
149 | case FILEID_INO32_GEN_PARENT: | ||
150 | case FILEID_INO32_GEN: | ||
151 | inode = xfs_nfs_get_inode(sb, fid->i32.ino, fid->i32.gen); | ||
152 | break; | ||
153 | case FILEID_INO32_GEN_PARENT | XFS_FILEID_TYPE_64FLAG: | ||
154 | case FILEID_INO32_GEN | XFS_FILEID_TYPE_64FLAG: | ||
155 | inode = xfs_nfs_get_inode(sb, fid64->ino, fid64->gen); | ||
156 | break; | ||
157 | } | ||
158 | |||
159 | if (!inode) | ||
160 | return NULL; | ||
161 | if (IS_ERR(inode)) | ||
162 | return ERR_PTR(PTR_ERR(inode)); | ||
163 | result = d_alloc_anon(inode); | ||
164 | if (!result) { | ||
165 | iput(inode); | ||
166 | return ERR_PTR(-ENOMEM); | ||
167 | } | ||
168 | return result; | ||
169 | } | ||
170 | |||
171 | STATIC struct dentry * | ||
172 | xfs_fs_fh_to_parent(struct super_block *sb, struct fid *fid, | ||
173 | int fh_len, int fileid_type) | ||
174 | { | ||
175 | struct xfs_fid64 *fid64 = (struct xfs_fid64 *)fid; | ||
176 | struct inode *inode = NULL; | ||
177 | struct dentry *result; | ||
178 | |||
179 | switch (fileid_type) { | ||
180 | case FILEID_INO32_GEN_PARENT: | ||
181 | inode = xfs_nfs_get_inode(sb, fid->i32.parent_ino, | ||
182 | fid->i32.parent_gen); | ||
183 | break; | ||
184 | case FILEID_INO32_GEN_PARENT | XFS_FILEID_TYPE_64FLAG: | ||
185 | inode = xfs_nfs_get_inode(sb, fid64->parent_ino, | ||
186 | fid64->parent_gen); | ||
187 | break; | ||
188 | } | ||
189 | |||
190 | if (!inode) | ||
191 | return NULL; | ||
192 | if (IS_ERR(inode)) | ||
193 | return ERR_PTR(PTR_ERR(inode)); | ||
152 | result = d_alloc_anon(inode); | 194 | result = d_alloc_anon(inode); |
153 | if (!result) { | 195 | if (!result) { |
154 | iput(inode); | 196 | iput(inode); |
155 | return ERR_PTR(-ENOMEM); | 197 | return ERR_PTR(-ENOMEM); |
156 | } | 198 | } |
@@ -178,9 +220,9 @@ xfs_fs_get_parent( | |||
178 | return parent; | 220 | return parent; |
179 | } | 221 | } |
180 | 222 | ||
181 | struct export_operations xfs_export_operations = { | 223 | const struct export_operations xfs_export_operations = { |
182 | .decode_fh = xfs_fs_decode_fh, | ||
183 | .encode_fh = xfs_fs_encode_fh, | 224 | .encode_fh = xfs_fs_encode_fh, |
225 | .fh_to_dentry = xfs_fs_fh_to_dentry, | ||
226 | .fh_to_parent = xfs_fs_fh_to_parent, | ||
184 | .get_parent = xfs_fs_get_parent, | 227 | .get_parent = xfs_fs_get_parent, |
185 | .get_dentry = xfs_fs_get_dentry, | ||
186 | }; | 228 | }; |
diff --git a/fs/xfs/linux-2.6/xfs_export.h b/fs/xfs/linux-2.6/xfs_export.h index 2f36071a86f7..3272b6ae7a35 100644 --- a/fs/xfs/linux-2.6/xfs_export.h +++ b/fs/xfs/linux-2.6/xfs_export.h | |||
@@ -59,50 +59,14 @@ | |||
59 | * a subdirectory) or use the "fsid" export option. | 59 | * a subdirectory) or use the "fsid" export option. |
60 | */ | 60 | */ |
61 | 61 | ||
62 | struct xfs_fid64 { | ||
63 | u64 ino; | ||
64 | u32 gen; | ||
65 | u64 parent_ino; | ||
66 | u32 parent_gen; | ||
67 | } __attribute__((packed)); | ||
68 | |||
62 | /* This flag goes on the wire. Don't play with it. */ | 69 | /* This flag goes on the wire. Don't play with it. */ |
63 | #define XFS_FILEID_TYPE_64FLAG 0x80 /* NFS fileid has 64bit inodes */ | 70 | #define XFS_FILEID_TYPE_64FLAG 0x80 /* NFS fileid has 64bit inodes */ |
64 | 71 | ||
65 | /* Calculate the length in u32 units of the fileid data */ | ||
66 | static inline int | ||
67 | xfs_fileid_length(int hasparent, int is64) | ||
68 | { | ||
69 | return hasparent ? (is64 ? 6 : 4) : (is64 ? 3 : 2); | ||
70 | } | ||
71 | |||
72 | /* | ||
73 | * Decode encoded inode information (either for the inode itself | ||
74 | * or the parent) into an xfs_fid_t structure. Advances and | ||
75 | * returns the new data pointer | ||
76 | */ | ||
77 | static inline __u32 * | ||
78 | xfs_fileid_decode_fid2(__u32 *p, xfs_fid_t *fid, int is64) | ||
79 | { | ||
80 | fid->fid_len = sizeof(xfs_fid_t) - sizeof(fid->fid_len); | ||
81 | fid->fid_pad = 0; | ||
82 | fid->fid_ino = *p++; | ||
83 | #if XFS_BIG_INUMS | ||
84 | if (is64) | ||
85 | fid->fid_ino |= (((__u64)(*p++)) << 32); | ||
86 | #endif | ||
87 | fid->fid_gen = *p++; | ||
88 | return p; | ||
89 | } | ||
90 | |||
91 | /* | ||
92 | * Encode inode information (either for the inode itself or the | ||
93 | * parent) into a fileid buffer. Advances and returns the new | ||
94 | * data pointer. | ||
95 | */ | ||
96 | static inline __u32 * | ||
97 | xfs_fileid_encode_inode(__u32 *p, struct inode *inode, int is64) | ||
98 | { | ||
99 | *p++ = (__u32)inode->i_ino; | ||
100 | #if XFS_BIG_INUMS | ||
101 | if (is64) | ||
102 | *p++ = (__u32)(inode->i_ino >> 32); | ||
103 | #endif | ||
104 | *p++ = inode->i_generation; | ||
105 | return p; | ||
106 | } | ||
107 | |||
108 | #endif /* __XFS_EXPORT_H__ */ | 72 | #endif /* __XFS_EXPORT_H__ */ |
diff --git a/fs/xfs/linux-2.6/xfs_super.h b/fs/xfs/linux-2.6/xfs_super.h index c78c23310fe8..3efcf45b14ab 100644 --- a/fs/xfs/linux-2.6/xfs_super.h +++ b/fs/xfs/linux-2.6/xfs_super.h | |||
@@ -118,7 +118,7 @@ extern int xfs_blkdev_get(struct xfs_mount *, const char *, | |||
118 | extern void xfs_blkdev_put(struct block_device *); | 118 | extern void xfs_blkdev_put(struct block_device *); |
119 | extern void xfs_blkdev_issue_flush(struct xfs_buftarg *); | 119 | extern void xfs_blkdev_issue_flush(struct xfs_buftarg *); |
120 | 120 | ||
121 | extern struct export_operations xfs_export_operations; | 121 | extern const struct export_operations xfs_export_operations; |
122 | 122 | ||
123 | #define XFS_M(sb) ((struct xfs_mount *)((sb)->s_fs_info)) | 123 | #define XFS_M(sb) ((struct xfs_mount *)((sb)->s_fs_info)) |
124 | 124 | ||