Whamcloud - gitweb
- merge 2 weeks of b1_4 fixes onto HEAD
[fs/lustre-release.git] / ldiskfs / kernel_patches / patches / iopen-2.6-suse.patch
1  fs/ext3/inode.c                    |    3 
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(-)
8
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
13 @@ -4,7 +4,7 @@
14  
15  obj-$(CONFIG_EXT3_FS) += ext3.o
16  
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
20  
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
26 @@ -37,6 +37,7 @@
27  #include <linux/mpage.h>
28  #include <linux/uio.h>
29  #include "xattr.h"
30 +#include "iopen.h"
31  #include "acl.h"
32  
33  /*
34 @@ -2472,6 +2473,9 @@
35         ei->i_acl = EXT3_ACL_NOT_CACHED;
36         ei->i_default_acl = EXT3_ACL_NOT_CACHED;
37  #endif
38 +       if (ext3_iopen_get_inode(inode))
39 +               return;
40 +
41         if (ext3_get_inode_loc(inode, &iloc, 0))
42                 goto bad_inode;
43         bh = iloc.bh;
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
48 @@ -0,0 +1,272 @@
49 +/*
50 + * linux/fs/ext3/iopen.c
51 + *
52 + * Special support for open by inode number
53 + *
54 + * Copyright (C) 2001 by Theodore Ts'o (tytso@alum.mit.edu).
55 + *
56 + * This file may be redistributed under the terms of the GNU General
57 + * Public License.
58 + *
59 + *
60 + * Invariants:
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.
65 + *
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
70 + * until it is gone.
71 + *
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.
77 + */
78 +
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>
87 +#include "iopen.h"
88 +
89 +#ifndef assert
90 +#define assert(test) J_ASSERT(test)
91 +#endif
92 +
93 +#define IOPEN_NAME_LEN 32
94 +
95 +/*
96 + * This implements looking up an inode by number.
97 + */
98 +static struct dentry *iopen_lookup(struct inode * dir, struct dentry *dentry,
99 +                                  struct nameidata *nd)
100 +{
101 +       struct inode *inode;
102 +       unsigned long ino;
103 +       struct list_head *lp;
104 +       struct dentry *alternate;
105 +       char buf[IOPEN_NAME_LEN];
106 +
107 +       if (dentry->d_name.len >= IOPEN_NAME_LEN)
108 +               return ERR_PTR(-ENAMETOOLONG);
109 +
110 +       memcpy(buf, dentry->d_name.name, dentry->d_name.len);
111 +       buf[dentry->d_name.len] = 0;
112 +
113 +       if (strcmp(buf, ".") == 0)
114 +               ino = dir->i_ino;
115 +       else if (strcmp(buf, "..") == 0)
116 +               ino = EXT3_ROOT_INO;
117 +       else
118 +               ino = simple_strtoul(buf, 0, 0);
119 +
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);
126 +
127 +       inode = iget(dir->i_sb, ino);
128 +       if (!inode)
129 +               return ERR_PTR(-EACCES);
130 +       if (is_bad_inode(inode)) {
131 +               iput(inode);
132 +               return ERR_PTR(-ENOENT);
133 +       }
134 +
135 +       assert(list_empty(&dentry->d_alias));           /* d_instantiate */
136 +       assert(d_unhashed(dentry));             /* d_rehash */
137 +
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));
143 +       }
144 +
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;
150 +               iput(inode);
151 +               spin_unlock(&dcache_lock);
152 +               return alternate;
153 +       }
154 +       dentry->d_flags |= DCACHE_DISCONNECTED;
155 +
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;
159 +
160 +       __d_rehash(dentry, 0);                          /* d_rehash */
161 +       spin_unlock(&dcache_lock);
162 +
163 +       return NULL;
164 +}
165 +
166 +#define do_switch(x,y) do { \
167 +       __typeof__ (x) __tmp = x; \
168 +       x = y; y = __tmp; } while (0)
169 +
170 +static inline void switch_names(struct dentry *dentry, struct dentry *target)
171 +{
172 +       const unsigned char *old_name, *new_name;
173 +
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;
183 +}
184 +
185 +/* This function is spliced into ext3_lookup and does the move of a
186 + * disconnected dentry (if it exists) to a connected dentry.
187 + */
188 +struct dentry *iopen_connect_dentry(struct dentry *dentry, struct inode *inode,
189 +                                   int rehash)
190 +{
191 +       struct dentry *tmp, *goal = NULL;
192 +       struct list_head *lp;
193 +
194 +       /* verify this dentry is really new */
195 +       assert(dentry->d_inode == NULL);
196 +       assert(list_empty(&dentry->d_alias));           /* d_instantiate */
197 +       if (rehash)
198 +               assert(d_unhashed(dentry));     /* d_rehash */
199 +       assert(list_empty(&dentry->d_subdirs));
200 +
201 +       spin_lock(&dcache_lock);
202 +       if (!inode)
203 +               goto do_rehash;
204 +
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);
211 +                       goal = tmp;
212 +                       dget_locked(goal);
213 +                       break;
214 +               }
215 +       }
216 +
217 +       if (!goal)
218 +               goto do_instantiate;
219 +
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);
226 +       iput(inode);
227 +
228 +       return goal;
229 +
230 +       /* d_add(), but don't drop dcache_lock before adding dentry to inode */
231 +do_instantiate:
232 +       list_add(&dentry->d_alias, &inode->i_dentry);   /* d_instantiate */
233 +       dentry->d_inode = inode;
234 +do_rehash:
235 +       if (rehash)
236 +               __d_rehash(dentry, 0);                  /* d_rehash */
237 +       spin_unlock(&dcache_lock);
238 +
239 +       return NULL;
240 +}
241 +
242 +/*
243 + * These are the special structures for the iopen pseudo directory.
244 + */
245 +
246 +static struct inode_operations iopen_inode_operations = {
247 +       lookup:         iopen_lookup,           /* BKL held */
248 +};
249 +
250 +static struct file_operations iopen_file_operations = {
251 +       read:           generic_read_dir,
252 +};
253 +
254 +static int match_dentry(struct dentry *dentry, const char *name)
255 +{
256 +       int     len;
257 +
258 +       len = strlen(name);
259 +       if (dentry->d_name.len != len)
260 +               return 0;
261 +       if (strncmp(dentry->d_name.name, name, len))
262 +               return 0;
263 +       return 1;
264 +}
265 +
266 +/*
267 + * This function is spliced into ext3_lookup and returns 1 the file
268 + * name is __iopen__ and dentry has been filled in appropriately.
269 + */
270 +int ext3_check_for_iopen(struct inode *dir, struct dentry *dentry)
271 +{
272 +       struct inode *inode;
273 +
274 +       if (dir->i_ino != EXT3_ROOT_INO ||
275 +           !test_opt(dir->i_sb, IOPEN) ||
276 +           !match_dentry(dentry, "__iopen__"))
277 +               return 0;
278 +
279 +       inode = iget(dir->i_sb, EXT3_BAD_INO);
280 +
281 +       if (!inode)
282 +               return 0;
283 +       d_add(dentry, inode);
284 +       return 1;
285 +}
286 +
287 +/*
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.
291 + */
292 +int ext3_iopen_get_inode(struct inode *inode)
293 +{
294 +       if (inode->i_ino != EXT3_BAD_INO)
295 +               return 0;
296 +
297 +       inode->i_mode = S_IFDIR | S_IRUSR | S_IXUSR;
298 +       if (test_opt(inode->i_sb, IOPEN_NOPRIV))
299 +               inode->i_mode |= 0777;
300 +       inode->i_uid = 0;
301 +       inode->i_gid = 0;
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
310 +                                        * size */
311 +       inode->i_blocks = 0;
312 +       inode->i_version = 1;
313 +       inode->i_generation = 0;
314 +
315 +       inode->i_op = &iopen_inode_operations;
316 +       inode->i_fop = &iopen_file_operations;
317 +       inode->i_mapping->a_ops = 0;
318 +
319 +       return 1;
320 +}
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
325 @@ -0,0 +1,15 @@
326 +/*
327 + * iopen.h
328 + *
329 + * Special support for opening files by inode number.
330 + *
331 + * Copyright (C) 2001 by Theodore Ts'o (tytso@alum.mit.edu).
332 + *
333 + * This file may be redistributed under the terms of the GNU General
334 + * Public License.
335 + */
336 +
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
345 @@ -37,6 +37,7 @@
346  #include <linux/buffer_head.h>
347  #include <linux/smp_lock.h>
348  #include "xattr.h"
349 +#include "iopen.h"
350  #include "acl.h"
351  
352  /*
353 @@ -979,6 +980,9 @@
354         if (dentry->d_name.len > EXT3_NAME_LEN)
355                 return ERR_PTR(-ENAMETOOLONG);
356  
357 +       if (ext3_check_for_iopen(dir, dentry))
358 +               return NULL;
359 +
360         bh = ext3_find_entry(dentry, &de);
361         inode = NULL;
362         if (bh) {
363 @@ -989,10 +993,8 @@
364                 if (!inode)
365                         return ERR_PTR(-EACCES);
366         }
367 -       if (inode)
368 -               return d_splice_alias(inode, dentry);
369 -       d_add(dentry, inode);
370 -       return NULL;
371 +
372 +       return iopen_connect_dentry(dentry, inode, 1);
373  }
374  
375  
376 @@ -2019,10 +2021,6 @@
377                               inode->i_nlink);
378         inode->i_version++;
379         inode->i_nlink = 0;
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
382 -        * recovery. */
383 -       inode->i_size = 0;
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 @@
388         return err;
389  }
390  
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)
394 +{
395 +       int err = ext3_add_entry(handle, dentry, inode);
396 +       if (!err) {
397 +               err = ext3_mark_inode_dirty(handle, inode);
398 +               if (err == 0) {
399 +                       (void)iopen_connect_dentry(dentry, inode, 0);
400 +                       return 0;
401 +               }
402 +       }
403 +       ext3_dec_count(handle, inode);
404 +       iput(inode);
405 +       return err;
406 +}
407 +
408  static int ext3_link (struct dentry * old_dentry,
409                 struct inode * dir, struct dentry *dentry)
410  {
411 @@ -2161,7 +2176,8 @@
412         ext3_inc_count(handle, inode);
413         atomic_inc(&inode->i_count);
414  
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);
419         return err;
420  }
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
425 @@ -536,7 +536,7 @@
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,
431         Opt_err,
432  };
433  
434 @@ -577,6 +577,9 @@
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"},
441         {Opt_err, NULL}
442  };
443  
444 @@ -772,6 +775,18 @@
445                         else
446                                 clear_opt(sbi->s_mount_opt, BARRIER);
447                         break;
448 +               case Opt_iopen:
449 +                       set_opt (sbi->s_mount_opt, IOPEN);
450 +                       clear_opt (sbi->s_mount_opt, IOPEN_NOPRIV);
451 +                       break;
452 +               case Opt_noiopen:
453 +                       clear_opt (sbi->s_mount_opt, IOPEN);
454 +                       clear_opt (sbi->s_mount_opt, IOPEN_NOPRIV);
455 +                       break;
456 +               case Opt_iopen_nopriv:
457 +                       set_opt (sbi->s_mount_opt, IOPEN);
458 +                       set_opt (sbi->s_mount_opt, IOPEN_NOPRIV);
459 +                       break;
460                 case Opt_ignore:
461                         break;
462                 default:
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
467 @@ -326,6 +326,8 @@
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 */
473  
474  /* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
475  #ifndef _LINUX_EXT2_FS_H