2 fs/ext3/iopen.c | 239 +++++++++++++++++++++++++++++++++++++
3 fs/ext3/iopen.h | 15 ++
4 fs/ext3/namei.c | 13 ++
5 fs/ext3/super.c | 17 ++
6 include/linux/ext3_fs.h | 2
7 7 files changed, 304 insertions(+), 1 deletion(-)
9 Index: linux-stage/fs/ext3/Makefile
10 ===================================================================
11 --- linux-stage.orig/fs/ext3/Makefile 2004-05-11 17:21:20.000000000 -0400
12 +++ linux-stage/fs/ext3/Makefile 2004-05-11 17:21:21.000000000 -0400
15 obj-$(CONFIG_EXT3_FS) += ext3.o
17 -ext3-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
18 +ext3-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o iopen.o \
19 ioctl.o namei.o super.o symlink.o hash.o
21 ext3-$(CONFIG_EXT3_FS_XATTR) += xattr.o xattr_user.o xattr_trusted.o
22 Index: linux-stage/fs/ext3/inode.c
23 ===================================================================
24 --- linux-stage.orig/fs/ext3/inode.c 2004-05-11 17:21:21.000000000 -0400
25 +++ linux-stage/fs/ext3/inode.c 2004-05-11 17:21:21.000000000 -0400
27 #include <linux/mpage.h>
28 #include <linux/uio.h>
35 ei->i_acl = EXT3_ACL_NOT_CACHED;
36 ei->i_default_acl = EXT3_ACL_NOT_CACHED;
38 + if (ext3_iopen_get_inode(inode))
41 if (ext3_get_inode_loc(inode, &iloc, 0))
44 Index: linux-stage/fs/ext3/iopen.c
45 ===================================================================
46 --- linux-stage.orig/fs/ext3/iopen.c 1969-12-31 19:00:00.000000000 -0500
47 +++ linux-stage/fs/ext3/iopen.c 2004-05-11 17:21:21.000000000 -0400
50 + * linux/fs/ext3/iopen.c
52 + * Special support for open by inode number
54 + * Copyright (C) 2001 by Theodore Ts'o (tytso@alum.mit.edu).
56 + * This file may be redistributed under the terms of the GNU General
61 + * - there is only ever a single DCACHE_NFSD_DISCONNECTED dentry alias
62 + * for an inode at one time.
63 + * - there are never both connected and DCACHE_NFSD_DISCONNECTED dentry
64 + * aliases on an inode at the same time.
66 + * If we have any connected dentry aliases for an inode, use one of those
67 + * in iopen_lookup(). Otherwise, we instantiate a single NFSD_DISCONNECTED
68 + * dentry for this inode, which thereafter will be found by the dcache
69 + * when looking up this inode number in __iopen__, so we don't return here
72 + * If we get an inode via a regular name lookup, then we "rename" the
73 + * NFSD_DISCONNECTED dentry to the proper name and parent. This ensures
74 + * existing users of the disconnected dentry will continue to use the same
75 + * dentry as the connected users, and there will never be both kinds of
76 + * dentry aliases at one time.
79 +#include <linux/sched.h>
80 +#include <linux/fs.h>
81 +#include <linux/ext3_jbd.h>
82 +#include <linux/jbd.h>
83 +#include <linux/ext3_fs.h>
84 +#include <linux/smp_lock.h>
85 +#include <linux/dcache.h>
86 +#include <linux/security.h>
90 +#define assert(test) J_ASSERT(test)
93 +#define IOPEN_NAME_LEN 32
96 + * This implements looking up an inode by number.
98 +static struct dentry *iopen_lookup(struct inode * dir, struct dentry *dentry,
99 + struct nameidata *nd)
101 + struct inode *inode;
103 + struct list_head *lp;
104 + struct dentry *alternate;
105 + char buf[IOPEN_NAME_LEN];
107 + if (dentry->d_name.len >= IOPEN_NAME_LEN)
108 + return ERR_PTR(-ENAMETOOLONG);
110 + memcpy(buf, dentry->d_name.name, dentry->d_name.len);
111 + buf[dentry->d_name.len] = 0;
113 + if (strcmp(buf, ".") == 0)
115 + else if (strcmp(buf, "..") == 0)
116 + ino = EXT3_ROOT_INO;
118 + ino = simple_strtoul(buf, 0, 0);
120 + if ((ino != EXT3_ROOT_INO &&
121 + //ino != EXT3_ACL_IDX_INO &&
122 + //ino != EXT3_ACL_DATA_INO &&
123 + ino < EXT3_FIRST_INO(dir->i_sb)) ||
124 + ino > le32_to_cpu(EXT3_SB(dir->i_sb)->s_es->s_inodes_count))
125 + return ERR_PTR(-ENOENT);
127 + inode = iget(dir->i_sb, ino);
129 + return ERR_PTR(-EACCES);
130 + if (is_bad_inode(inode)) {
132 + return ERR_PTR(-ENOENT);
135 + assert(list_empty(&dentry->d_alias)); /* d_instantiate */
136 + assert(d_unhashed(dentry)); /* d_rehash */
138 + /* preferrably return a connected dentry */
139 + spin_lock(&dcache_lock);
140 + list_for_each(lp, &inode->i_dentry) {
141 + alternate = list_entry(lp, struct dentry, d_alias);
142 + assert(!(alternate->d_flags & DCACHE_DISCONNECTED));
145 + if (!list_empty(&inode->i_dentry)) {
146 + alternate = list_entry(inode->i_dentry.next,
147 + struct dentry, d_alias);
148 + dget_locked(alternate);
149 + alternate->d_vfs_flags |= DCACHE_REFERENCED;
151 + spin_unlock(&dcache_lock);
154 + dentry->d_flags |= DCACHE_DISCONNECTED;
156 + /* d_add(), but don't drop dcache_lock before adding dentry to inode */
157 + list_add(&dentry->d_alias, &inode->i_dentry); /* d_instantiate */
158 + dentry->d_inode = inode;
160 + __d_rehash(dentry, 0); /* d_rehash */
161 + spin_unlock(&dcache_lock);
166 +#define do_switch(x,y) do { \
167 + __typeof__ (x) __tmp = x; \
168 + x = y; y = __tmp; } while (0)
170 +static inline void switch_names(struct dentry *dentry, struct dentry *target)
172 + const unsigned char *old_name, *new_name;
174 + memcpy(dentry->d_iname, target->d_iname, DNAME_INLINE_LEN);
175 + old_name = target->d_name.name;
176 + new_name = dentry->d_name.name;
177 + if (old_name == target->d_iname)
178 + old_name = dentry->d_iname;
179 + if (new_name == dentry->d_iname)
180 + new_name = target->d_iname;
181 + target->d_name.name = new_name;
182 + dentry->d_name.name = old_name;
185 +/* This function is spliced into ext3_lookup and does the move of a
186 + * disconnected dentry (if it exists) to a connected dentry.
188 +struct dentry *iopen_connect_dentry(struct dentry *dentry, struct inode *inode,
191 + struct dentry *tmp, *goal = NULL;
192 + struct list_head *lp;
194 + /* verify this dentry is really new */
195 + assert(dentry->d_inode == NULL);
196 + assert(list_empty(&dentry->d_alias)); /* d_instantiate */
198 + assert(d_unhashed(dentry)); /* d_rehash */
199 + assert(list_empty(&dentry->d_subdirs));
201 + spin_lock(&dcache_lock);
205 + /* preferrably return a connected dentry */
206 + list_for_each(lp, &inode->i_dentry) {
207 + tmp = list_entry(lp, struct dentry, d_alias);
208 + if (tmp->d_flags & DCACHE_DISCONNECTED) {
209 + assert(tmp->d_alias.next == &inode->i_dentry);
210 + assert(tmp->d_alias.prev == &inode->i_dentry);
218 + goto do_instantiate;
220 + /* Move the goal to the de hash queue */
221 + goal->d_flags &= ~ DCACHE_DISCONNECTED;
222 + security_d_instantiate(goal, inode);
223 + __d_rehash(dentry, 0);
224 + __d_move(goal, dentry);
225 + spin_unlock(&dcache_lock);
230 + /* d_add(), but don't drop dcache_lock before adding dentry to inode */
232 + list_add(&dentry->d_alias, &inode->i_dentry); /* d_instantiate */
233 + dentry->d_inode = inode;
236 + __d_rehash(dentry, 0); /* d_rehash */
237 + spin_unlock(&dcache_lock);
243 + * These are the special structures for the iopen pseudo directory.
246 +static struct inode_operations iopen_inode_operations = {
247 + lookup: iopen_lookup, /* BKL held */
250 +static struct file_operations iopen_file_operations = {
251 + read: generic_read_dir,
254 +static int match_dentry(struct dentry *dentry, const char *name)
258 + len = strlen(name);
259 + if (dentry->d_name.len != len)
261 + if (strncmp(dentry->d_name.name, name, len))
267 + * This function is spliced into ext3_lookup and returns 1 the file
268 + * name is __iopen__ and dentry has been filled in appropriately.
270 +int ext3_check_for_iopen(struct inode *dir, struct dentry *dentry)
272 + struct inode *inode;
274 + if (dir->i_ino != EXT3_ROOT_INO ||
275 + !test_opt(dir->i_sb, IOPEN) ||
276 + !match_dentry(dentry, "__iopen__"))
279 + inode = iget(dir->i_sb, EXT3_BAD_INO);
283 + d_add(dentry, inode);
288 + * This function is spliced into read_inode; it returns 1 if inode
289 + * number is the one for /__iopen__, in which case the inode is filled
290 + * in appropriately. Otherwise, this fuction returns 0.
292 +int ext3_iopen_get_inode(struct inode *inode)
294 + if (inode->i_ino != EXT3_BAD_INO)
297 + inode->i_mode = S_IFDIR | S_IRUSR | S_IXUSR;
298 + if (test_opt(inode->i_sb, IOPEN_NOPRIV))
299 + inode->i_mode |= 0777;
302 + inode->i_nlink = 1;
303 + inode->i_size = 4096;
304 + inode->i_atime = CURRENT_TIME;
305 + inode->i_ctime = CURRENT_TIME;
306 + inode->i_mtime = CURRENT_TIME;
307 + EXT3_I(inode)->i_dtime = 0;
308 + inode->i_blksize = PAGE_SIZE; /* This is the optimal IO size
309 + * (for stat), not the fs block
311 + inode->i_blocks = 0;
312 + inode->i_version = 1;
313 + inode->i_generation = 0;
315 + inode->i_op = &iopen_inode_operations;
316 + inode->i_fop = &iopen_file_operations;
317 + inode->i_mapping->a_ops = 0;
321 Index: linux-stage/fs/ext3/iopen.h
322 ===================================================================
323 --- linux-stage.orig/fs/ext3/iopen.h 1969-12-31 19:00:00.000000000 -0500
324 +++ linux-stage/fs/ext3/iopen.h 2004-05-11 17:21:21.000000000 -0400
329 + * Special support for opening files by inode number.
331 + * Copyright (C) 2001 by Theodore Ts'o (tytso@alum.mit.edu).
333 + * This file may be redistributed under the terms of the GNU General
337 +extern int ext3_check_for_iopen(struct inode *dir, struct dentry *dentry);
338 +extern int ext3_iopen_get_inode(struct inode *inode);
339 +extern struct dentry *iopen_connect_dentry(struct dentry *dentry,
340 + struct inode *inode, int rehash);
341 Index: linux-stage/fs/ext3/namei.c
342 ===================================================================
343 --- linux-stage.orig/fs/ext3/namei.c 2004-05-11 17:21:20.000000000 -0400
344 +++ linux-stage/fs/ext3/namei.c 2004-05-11 17:21:21.000000000 -0400
346 #include <linux/buffer_head.h>
347 #include <linux/smp_lock.h>
354 if (dentry->d_name.len > EXT3_NAME_LEN)
355 return ERR_PTR(-ENAMETOOLONG);
357 + if (ext3_check_for_iopen(dir, dentry))
360 bh = ext3_find_entry(dentry, &de);
365 return ERR_PTR(-EACCES);
368 - return d_splice_alias(inode, dentry);
369 - d_add(dentry, inode);
372 + return iopen_connect_dentry(dentry, inode, 1);
376 @@ -2019,10 +2021,6 @@
380 - /* There's no need to set i_disksize: the fact that i_nlink is
381 - * zero will ensure that the right thing happens during any
384 ext3_orphan_add(handle, inode);
385 inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
386 ext3_mark_inode_dirty(handle, inode);
387 @@ -2139,6 +2137,23 @@
391 +/* Like ext3_add_nondir() except for call to iopen_connect_dentry */
392 +static int ext3_add_link(handle_t *handle, struct dentry *dentry,
393 + struct inode *inode)
395 + int err = ext3_add_entry(handle, dentry, inode);
397 + err = ext3_mark_inode_dirty(handle, inode);
399 + (void)iopen_connect_dentry(dentry, inode, 0);
403 + ext3_dec_count(handle, inode);
408 static int ext3_link (struct dentry * old_dentry,
409 struct inode * dir, struct dentry *dentry)
411 @@ -2161,7 +2176,8 @@
412 ext3_inc_count(handle, inode);
413 atomic_inc(&inode->i_count);
415 - err = ext3_add_nondir(handle, dentry, inode);
416 + err = ext3_add_link(handle, dentry, inode);
417 + ext3_orphan_del(handle,inode);
418 ext3_journal_stop(handle);
421 Index: linux-stage/fs/ext3/super.c
422 ===================================================================
423 --- linux-stage.orig/fs/ext3/super.c 2004-05-11 17:21:21.000000000 -0400
424 +++ linux-stage/fs/ext3/super.c 2004-05-11 17:44:53.000000000 -0400
426 Opt_user_xattr, Opt_nouser_xattr, Opt_acl, Opt_noacl, Opt_noload,
427 Opt_commit, Opt_journal_update, Opt_journal_inum,
428 Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback,
429 - Opt_ignore, Opt_barrier,
430 + Opt_ignore, Opt_barrier, Opt_iopen, Opt_noiopen, Opt_iopen_nopriv,
435 {Opt_ignore, "quota"},
436 {Opt_ignore, "usrquota"},
437 {Opt_barrier, "barrier=%u"},
438 + {Opt_iopen, "iopen"},
439 + {Opt_noiopen, "noiopen"},
440 + {Opt_iopen_nopriv, "iopen_nopriv"},
446 clear_opt(sbi->s_mount_opt, BARRIER);
449 + set_opt (sbi->s_mount_opt, IOPEN);
450 + clear_opt (sbi->s_mount_opt, IOPEN_NOPRIV);
453 + clear_opt (sbi->s_mount_opt, IOPEN);
454 + clear_opt (sbi->s_mount_opt, IOPEN_NOPRIV);
456 + case Opt_iopen_nopriv:
457 + set_opt (sbi->s_mount_opt, IOPEN);
458 + set_opt (sbi->s_mount_opt, IOPEN_NOPRIV);
463 Index: linux-stage/include/linux/ext3_fs.h
464 ===================================================================
465 --- linux-stage.orig/include/linux/ext3_fs.h 2004-05-11 17:21:20.000000000 -0400
466 +++ linux-stage/include/linux/ext3_fs.h 2004-05-11 17:21:21.000000000 -0400
468 #define EXT3_MOUNT_XATTR_USER 0x4000 /* Extended user attributes */
469 #define EXT3_MOUNT_POSIX_ACL 0x8000 /* POSIX Access Control Lists */
470 #define EXT3_MOUNT_BARRIER 0x10000 /* Use block barriers */
471 +#define EXT3_MOUNT_IOPEN 0x20000 /* Allow access via iopen */
472 +#define EXT3_MOUNT_IOPEN_NOPRIV 0x40000 /* Make iopen world-readable */
474 /* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
475 #ifndef _LINUX_EXT2_FS_H