Whamcloud - gitweb
Branch HEAD
[fs/lustre-release.git] / lustre / kernel_patches / patches / iopen-2.6.10-fc3.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-2.6.10/include/linux/ext3_fs.h
10 ===================================================================
11 --- linux-2.6.10.orig/include/linux/ext3_fs.h   2005-04-05 12:25:13.635136112 +0800
12 +++ linux-2.6.10/include/linux/ext3_fs.h        2005-04-05 12:25:13.801110880 +0800
13 @@ -357,6 +357,8 @@
14  #define EXT3_MOUNT_RESERVATION         0x10000 /* Preallocation */
15  #define EXT3_MOUNT_BARRIER             0x20000 /* Use block barriers */
16  #define EXT3_MOUNT_PDIROPS             0x800000/* Parallel dir operations */
17 +#define EXT3_MOUNT_IOPEN               0x40000 /* Allow access via iopen */
18 +#define EXT3_MOUNT_IOPEN_NOPRIV                0x80000 /* Make iopen world-readable */
19  
20  /* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
21  #ifndef _LINUX_EXT2_FS_H
22 Index: linux-2.6.10/fs/ext3/inode.c
23 ===================================================================
24 --- linux-2.6.10.orig/fs/ext3/inode.c   2005-04-05 12:25:13.726122280 +0800
25 +++ linux-2.6.10/fs/ext3/inode.c        2005-04-05 12:25:13.794111944 +0800
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 @@ -2411,6 +2412,9 @@
35  #endif
36         ei->i_rsv_window.rsv_end = EXT3_RESERVE_WINDOW_NOT_ALLOCATED;
37  
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-2.6.10/fs/ext3/super.c
45 ===================================================================
46 --- linux-2.6.10.orig/fs/ext3/super.c   2005-04-05 12:25:13.728121976 +0800
47 +++ linux-2.6.10/fs/ext3/super.c        2005-04-05 12:25:13.797111488 +0800
48 @@ -592,6 +592,7 @@
49         Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback,
50         Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota,
51         Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_pdirops,
52 +       Opt_iopen, Opt_noiopen, Opt_iopen_nopriv,
53         Opt_ignore, Opt_barrier, Opt_err, Opt_resize,
54  };
55  
56 @@ -641,6 +642,9 @@
57         {Opt_ignore, "usrquota"},
58         {Opt_barrier, "barrier=%u"},
59         {Opt_pdirops, "pdirops"},
60 +       {Opt_iopen,  "iopen"},
61 +       {Opt_noiopen,  "noiopen"},
62 +       {Opt_iopen_nopriv,  "iopen_nopriv"},
63         {Opt_err, NULL},
64         {Opt_resize, "resize"},
65  };
66 @@ -921,6 +925,18 @@
67                         else
68                                 clear_opt(sbi->s_mount_opt, BARRIER);
69                         break;
70 +               case Opt_iopen:
71 +                       set_opt (sbi->s_mount_opt, IOPEN);
72 +                       clear_opt (sbi->s_mount_opt, IOPEN_NOPRIV);
73 +                       break;
74 +               case Opt_noiopen:
75 +                       clear_opt (sbi->s_mount_opt, IOPEN);
76 +                       clear_opt (sbi->s_mount_opt, IOPEN_NOPRIV);
77 +                       break;
78 +               case Opt_iopen_nopriv:
79 +                       set_opt (sbi->s_mount_opt, IOPEN);
80 +                       set_opt (sbi->s_mount_opt, IOPEN_NOPRIV);
81 +                       break;
82                 case Opt_ignore:
83                         break;
84                 case Opt_resize:
85 Index: linux-2.6.10/fs/ext3/iopen.c
86 ===================================================================
87 --- linux-2.6.10.orig/fs/ext3/iopen.c   2005-04-05 19:01:49.158500672 +0800
88 +++ linux-2.6.10/fs/ext3/iopen.c        2005-04-05 12:25:13.791112400 +0800
89 @@ -0,0 +1,274 @@
90 +/*
91 + * linux/fs/ext3/iopen.c
92 + *
93 + * Special support for open by inode number
94 + *
95 + * Copyright (C) 2001 by Theodore Ts'o (tytso@alum.mit.edu).
96 + *
97 + * This file may be redistributed under the terms of the GNU General
98 + * Public License.
99 + *
100 + *
101 + * Invariants:
102 + *   - there is only ever a single DCACHE_NFSD_DISCONNECTED dentry alias
103 + *     for an inode at one time.
104 + *   - there are never both connected and DCACHE_NFSD_DISCONNECTED dentry
105 + *     aliases on an inode at the same time.
106 + *
107 + * If we have any connected dentry aliases for an inode, use one of those
108 + * in iopen_lookup().  Otherwise, we instantiate a single NFSD_DISCONNECTED
109 + * dentry for this inode, which thereafter will be found by the dcache
110 + * when looking up this inode number in __iopen__, so we don't return here
111 + * until it is gone.
112 + *
113 + * If we get an inode via a regular name lookup, then we "rename" the
114 + * NFSD_DISCONNECTED dentry to the proper name and parent.  This ensures
115 + * existing users of the disconnected dentry will continue to use the same
116 + * dentry as the connected users, and there will never be both kinds of
117 + * dentry aliases at one time.
118 + */
119 +
120 +#include <linux/sched.h>
121 +#include <linux/fs.h>
122 +#include <linux/ext3_jbd.h>
123 +#include <linux/jbd.h>
124 +#include <linux/ext3_fs.h>
125 +#include <linux/smp_lock.h>
126 +#include <linux/dcache.h>
127 +#include <linux/security.h>
128 +#include "iopen.h"
129 +
130 +#ifndef assert
131 +#define assert(test) J_ASSERT(test)
132 +#endif
133 +
134 +#define IOPEN_NAME_LEN 32
135 +
136 +/*
137 + * This implements looking up an inode by number.
138 + */
139 +static struct dentry *iopen_lookup(struct inode * dir, struct dentry *dentry,
140 +                                  struct nameidata *nd)
141 +{
142 +       struct inode *inode;
143 +       unsigned long ino;
144 +       struct list_head *lp;
145 +       struct dentry *alternate;
146 +       char buf[IOPEN_NAME_LEN];
147 +
148 +       if (dentry->d_name.len >= IOPEN_NAME_LEN)
149 +               return ERR_PTR(-ENAMETOOLONG);
150 +
151 +       memcpy(buf, dentry->d_name.name, dentry->d_name.len);
152 +       buf[dentry->d_name.len] = 0;
153 +
154 +       if (strcmp(buf, ".") == 0)
155 +               ino = dir->i_ino;
156 +       else if (strcmp(buf, "..") == 0)
157 +               ino = EXT3_ROOT_INO;
158 +       else
159 +               ino = simple_strtoul(buf, 0, 0);
160 +
161 +       if ((ino != EXT3_ROOT_INO &&
162 +            //ino != EXT3_ACL_IDX_INO &&
163 +            //ino != EXT3_ACL_DATA_INO &&
164 +            ino < EXT3_FIRST_INO(dir->i_sb)) ||
165 +           ino > le32_to_cpu(EXT3_SB(dir->i_sb)->s_es->s_inodes_count))
166 +               return ERR_PTR(-ENOENT);
167 +
168 +       inode = iget(dir->i_sb, ino);
169 +       if (!inode)
170 +               return ERR_PTR(-EACCES);
171 +       if (is_bad_inode(inode)) {
172 +               iput(inode);
173 +               return ERR_PTR(-ENOENT);
174 +       }
175 +
176 +       assert(list_empty(&dentry->d_alias));           /* d_instantiate */
177 +       assert(d_unhashed(dentry));             /* d_rehash */
178 +
179 +       /* preferrably return a connected dentry */
180 +       spin_lock(&dcache_lock);
181 +       list_for_each(lp, &inode->i_dentry) {
182 +               alternate = list_entry(lp, struct dentry, d_alias);
183 +               assert(!(alternate->d_flags & DCACHE_DISCONNECTED));
184 +       }
185 +
186 +       if (!list_empty(&inode->i_dentry)) {
187 +               alternate = list_entry(inode->i_dentry.next,
188 +                                      struct dentry, d_alias);
189 +               dget_locked(alternate);
190 +               spin_lock(&alternate->d_lock);
191 +               alternate->d_flags |= DCACHE_REFERENCED;
192 +               spin_unlock(&alternate->d_lock);
193 +               iput(inode);
194 +               spin_unlock(&dcache_lock);
195 +               return alternate;
196 +       }
197 +       dentry->d_flags |= DCACHE_DISCONNECTED;
198 +
199 +       /* d_add(), but don't drop dcache_lock before adding dentry to inode */
200 +       list_add(&dentry->d_alias, &inode->i_dentry);   /* d_instantiate */
201 +       dentry->d_inode = inode;
202 +
203 +       __d_rehash(dentry);                             /* d_rehash */
204 +       spin_unlock(&dcache_lock);
205 +
206 +       return NULL;
207 +}
208 +
209 +#define do_switch(x,y) do { \
210 +       __typeof__ (x) __tmp = x; \
211 +       x = y; y = __tmp; } while (0)
212 +
213 +static inline void switch_names(struct dentry *dentry, struct dentry *target)
214 +{
215 +       const unsigned char *old_name, *new_name;
216 +
217 +       memcpy(dentry->d_iname, target->d_iname, DNAME_INLINE_LEN_MIN);
218 +       old_name = target->d_name.name;
219 +       new_name = dentry->d_name.name;
220 +       if (old_name == target->d_iname)
221 +               old_name = dentry->d_iname;
222 +       if (new_name == dentry->d_iname)
223 +               new_name = target->d_iname;
224 +       target->d_name.name = new_name;
225 +       dentry->d_name.name = old_name;
226 +}
227 +
228 +/* This function is spliced into ext3_lookup and does the move of a
229 + * disconnected dentry (if it exists) to a connected dentry.
230 + */
231 +struct dentry *iopen_connect_dentry(struct dentry *dentry, struct inode *inode,
232 +                                   int rehash)
233 +{
234 +       struct dentry *tmp, *goal = NULL;
235 +       struct list_head *lp;
236 +
237 +       /* verify this dentry is really new */
238 +       assert(dentry->d_inode == NULL);
239 +       assert(list_empty(&dentry->d_alias));           /* d_instantiate */
240 +       if (rehash)
241 +               assert(d_unhashed(dentry));     /* d_rehash */
242 +       assert(list_empty(&dentry->d_subdirs));
243 +
244 +       spin_lock(&dcache_lock);
245 +       if (!inode)
246 +               goto do_rehash;
247 +
248 +       /* preferrably return a connected dentry */
249 +       list_for_each(lp, &inode->i_dentry) {
250 +               tmp = list_entry(lp, struct dentry, d_alias);
251 +               if (tmp->d_flags & DCACHE_DISCONNECTED) {
252 +                       assert(tmp->d_alias.next == &inode->i_dentry);
253 +                       assert(tmp->d_alias.prev == &inode->i_dentry);
254 +                       goal = tmp;
255 +                       dget_locked(goal);
256 +                       break;
257 +               }
258 +       }
259 +
260 +       if (!goal)
261 +               goto do_instantiate;
262 +
263 +       /* Move the goal to the de hash queue */
264 +       goal->d_flags &= ~ DCACHE_DISCONNECTED;
265 +       security_d_instantiate(goal, inode);
266 +       __d_rehash(dentry);
267 +       __d_move(goal, dentry);
268 +       spin_unlock(&dcache_lock);
269 +       iput(inode);
270 +
271 +       return goal;
272 +
273 +       /* d_add(), but don't drop dcache_lock before adding dentry to inode */
274 +do_instantiate:
275 +       list_add(&dentry->d_alias, &inode->i_dentry);   /* d_instantiate */
276 +       dentry->d_inode = inode;
277 +do_rehash:
278 +       if (rehash)
279 +               __d_rehash(dentry);                     /* d_rehash */
280 +       spin_unlock(&dcache_lock);
281 +
282 +       return NULL;
283 +}
284 +
285 +/*
286 + * These are the special structures for the iopen pseudo directory.
287 + */
288 +
289 +static struct inode_operations iopen_inode_operations = {
290 +       lookup:         iopen_lookup,           /* BKL held */
291 +};
292 +
293 +static struct file_operations iopen_file_operations = {
294 +       read:           generic_read_dir,
295 +};
296 +
297 +static int match_dentry(struct dentry *dentry, const char *name)
298 +{
299 +       int     len;
300 +
301 +       len = strlen(name);
302 +       if (dentry->d_name.len != len)
303 +               return 0;
304 +       if (strncmp(dentry->d_name.name, name, len))
305 +               return 0;
306 +       return 1;
307 +}
308 +
309 +/*
310 + * This function is spliced into ext3_lookup and returns 1 the file
311 + * name is __iopen__ and dentry has been filled in appropriately.
312 + */
313 +int ext3_check_for_iopen(struct inode *dir, struct dentry *dentry)
314 +{
315 +       struct inode *inode;
316 +
317 +       if (dir->i_ino != EXT3_ROOT_INO ||
318 +           !test_opt(dir->i_sb, IOPEN) ||
319 +           !match_dentry(dentry, "__iopen__"))
320 +               return 0;
321 +
322 +       inode = iget(dir->i_sb, EXT3_BAD_INO);
323 +
324 +       if (!inode)
325 +               return 0;
326 +       d_add(dentry, inode);
327 +       return 1;
328 +}
329 +
330 +/*
331 + * This function is spliced into read_inode; it returns 1 if inode
332 + * number is the one for /__iopen__, in which case the inode is filled
333 + * in appropriately.  Otherwise, this fuction returns 0.
334 + */
335 +int ext3_iopen_get_inode(struct inode *inode)
336 +{
337 +       if (inode->i_ino != EXT3_BAD_INO)
338 +               return 0;
339 +
340 +       inode->i_mode = S_IFDIR | S_IRUSR | S_IXUSR;
341 +       if (test_opt(inode->i_sb, IOPEN_NOPRIV))
342 +               inode->i_mode |= 0777;
343 +       inode->i_uid = 0;
344 +       inode->i_gid = 0;
345 +       inode->i_nlink = 1;
346 +       inode->i_size = 4096;
347 +       inode->i_atime = CURRENT_TIME;
348 +       inode->i_ctime = CURRENT_TIME;
349 +       inode->i_mtime = CURRENT_TIME;
350 +       EXT3_I(inode)->i_dtime = 0;
351 +       inode->i_blksize = PAGE_SIZE;   /* This is the optimal IO size
352 +                                        * (for stat), not the fs block
353 +                                        * size */
354 +       inode->i_blocks = 0;
355 +       inode->i_version = 1;
356 +       inode->i_generation = 0;
357 +
358 +       inode->i_op = &iopen_inode_operations;
359 +       inode->i_fop = &iopen_file_operations;
360 +       inode->i_mapping->a_ops = 0;
361 +
362 +       return 1;
363 +}
364 Index: linux-2.6.10/fs/ext3/iopen.h
365 ===================================================================
366 --- linux-2.6.10.orig/fs/ext3/iopen.h   2005-04-05 19:01:49.158500672 +0800
367 +++ linux-2.6.10/fs/ext3/iopen.h        2005-04-05 12:25:13.792112248 +0800
368 @@ -0,0 +1,15 @@
369 +/*
370 + * iopen.h
371 + *
372 + * Special support for opening files by inode number.
373 + *
374 + * Copyright (C) 2001 by Theodore Ts'o (tytso@alum.mit.edu).
375 + *
376 + * This file may be redistributed under the terms of the GNU General
377 + * Public License.
378 + */
379 +
380 +extern int ext3_check_for_iopen(struct inode *dir, struct dentry *dentry);
381 +extern int ext3_iopen_get_inode(struct inode *inode);
382 +extern struct dentry *iopen_connect_dentry(struct dentry *dentry,
383 +                                          struct inode *inode, int rehash);
384 Index: linux-2.6.10/fs/ext3/Makefile
385 ===================================================================
386 --- linux-2.6.10.orig/fs/ext3/Makefile  2004-12-25 05:33:52.000000000 +0800
387 +++ linux-2.6.10/fs/ext3/Makefile       2005-04-05 12:26:06.897039072 +0800
388 @@ -5,7 +5,7 @@
389  obj-$(CONFIG_EXT3_FS) += ext3.o
390  
391  ext3-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
392 -          ioctl.o namei.o super.o symlink.o hash.o resize.o
393 +          ioctl.o namei.o super.o symlink.o hash.o resize.o iopen.o
394  
395  ext3-$(CONFIG_EXT3_FS_XATTR)    += xattr.o xattr_user.o xattr_trusted.o
396  ext3-$(CONFIG_EXT3_FS_POSIX_ACL) += acl.o
397 Index: linux-2.6.10/fs/ext3/namei.c
398 ===================================================================
399 --- linux-2.6.10.orig/fs/ext3/namei.c   2005-04-05 12:25:13.633136416 +0800
400 +++ linux-2.6.10/fs/ext3/namei.c        2005-04-05 12:25:13.799111184 +0800
401 @@ -37,6 +37,7 @@
402  #include <linux/buffer_head.h>
403  #include <linux/smp_lock.h>
404  #include "xattr.h"
405 +#include "iopen.h"
406  #include "acl.h"
407  
408  /*
409 @@ -1140,6 +1141,9 @@
410         if (dentry->d_name.len > EXT3_NAME_LEN)
411                 return ERR_PTR(-ENAMETOOLONG);
412  
413 +       if (ext3_check_for_iopen(dir, dentry))
414 +               return NULL;
415 +
416         bh = ext3_find_entry(dentry, &de, 0, &lock);
417         inode = NULL;
418         if (bh) {
419 @@ -1151,10 +1155,8 @@
420                 if (!inode)
421                         return ERR_PTR(-EACCES);
422         }
423 -       if (inode)
424 -               return d_splice_alias(inode, dentry);
425 -       d_add(dentry, inode);
426 -       return NULL;
427 +
428 +       return iopen_connect_dentry(dentry, inode, 1);
429  }
430  
431  
432 @@ -2367,10 +2369,6 @@
433                               inode->i_nlink);
434         inode->i_version++;
435         inode->i_nlink = 0;
436 -       /* There's no need to set i_disksize: the fact that i_nlink is
437 -        * zero will ensure that the right thing happens during any
438 -        * recovery. */
439 -       inode->i_size = 0;
440         ext3_orphan_add(handle, inode);
441         inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
442         ext3_mark_inode_dirty(handle, inode);
443 @@ -2497,6 +2495,23 @@
444         return err;
445  }
446  
447 +/* Like ext3_add_nondir() except for call to iopen_connect_dentry */
448 +static int ext3_add_link(handle_t *handle, struct dentry *dentry,
449 +                        struct inode *inode)
450 +{
451 +       int err = ext3_add_entry(handle, dentry, inode);
452 +       if (!err) {
453 +               err = ext3_mark_inode_dirty(handle, inode);
454 +               if (err == 0) {
455 +                       dput(iopen_connect_dentry(dentry, inode, 0));
456 +                       return 0;
457 +               }
458 +       }
459 +       ext3_dec_count(handle, inode);
460 +       iput(inode);
461 +       return err;
462 +}
463 +
464  static int ext3_link (struct dentry * old_dentry,
465                 struct inode * dir, struct dentry *dentry)
466  {
467 @@ -2520,7 +2535,8 @@
468         ext3_inc_count(handle, inode);
469         atomic_inc(&inode->i_count);
470  
471 -       err = ext3_add_nondir(handle, dentry, inode);
472 +       err = ext3_add_link(handle, dentry, inode);
473 +       ext3_orphan_del(handle,inode);
474         ext3_journal_stop(handle);
475         if (err == -ENOSPC && ext3_should_retry_alloc(dir->i_sb, &retries))
476                 goto retry;