]> git.pld-linux.org Git - packages/kernel.git/blob - linux-2.4.22-reiserfs-acl+ea.patch
- obsolete
[packages/kernel.git] / linux-2.4.22-reiserfs-acl+ea.patch
1 diff -urN linux-2.4.22/fs/Config.in linux-2.4.22-aclea/fs/Config.in
2 --- linux-2.4.22/fs/Config.in   2003-09-12 17:01:18.000000000 +0200
3 +++ linux-2.4.22-aclea/fs/Config.in     2003-09-12 17:19:43.000000000 +0200
4 @@ -13,6 +13,10 @@
5  tristate 'Reiserfs support' CONFIG_REISERFS_FS
6  dep_mbool '  Enable reiserfs debug mode' CONFIG_REISERFS_CHECK $CONFIG_REISERFS_FS
7  dep_mbool '  Stats in /proc/fs/reiserfs' CONFIG_REISERFS_PROC_INFO $CONFIG_REISERFS_FS
8 +dep_mbool '  ReiserFS extended attributes' CONFIG_REISERFS_FS_XATTR $CONFIG_REISERFS_FS
9 +dep_mbool '  ReiserFS extended user attributes' CONFIG_REISERFS_FS_XATTR_USER $CONFIG_REISERFS_FS_XATTR
10 +dep_mbool '  ReiserFS trusted extended attributes' CONFIG_REISERFS_FS_XATTR_TRUSTED $CONFIG_REISERFS_FS_XATTR
11 +dep_mbool '  ReiserFS POSIX Access Control Lists' CONFIG_REISERFS_FS_POSIX_ACL $CONFIG_REISERFS_FS_XATTR $CONFIG_FS_POSIX_ACL
12  
13  dep_tristate 'ADFS file system support (EXPERIMENTAL)' CONFIG_ADFS_FS $CONFIG_EXPERIMENTAL
14  dep_mbool '  ADFS write support (DANGEROUS)' CONFIG_ADFS_FS_RW $CONFIG_ADFS_FS $CONFIG_EXPERIMENTAL
15 diff -urN linux-2.4.22/fs/reiserfs/Makefile linux-2.4.22-aclea/fs/reiserfs/Makefile
16 --- linux-2.4.22/fs/reiserfs/Makefile   2003-08-25 13:44:43.000000000 +0200
17 +++ linux-2.4.22-aclea/fs/reiserfs/Makefile     2003-09-12 17:19:43.000000000 +0200
18 @@ -11,6 +11,11 @@
19  obj-y   := bitmap.o do_balan.o namei.o inode.o file.o dir.o fix_node.o super.o prints.o objectid.o \
20  lbalance.o ibalance.o stree.o hashes.o buffer2.o tail_conversion.o journal.o resize.o item_ops.o ioctl.o procfs.o
21  
22 +obj-$(CONFIG_REISERFS_FS_XATTR) += xattr.o
23 +obj-$(CONFIG_REISERFS_FS_XATTR_USER) += xattr_user.o
24 +obj-$(CONFIG_REISERFS_FS_XATTR_TRUSTED) += xattr_trusted.o
25 +obj-$(CONFIG_REISERFS_FS_POSIX_ACL) += xattr_acl.o
26 +
27  obj-m   := $(O_TARGET)
28  
29  # gcc -O2 (the kernel default)  is overaggressive on ppc32 when many inline
30 diff -urN linux-2.4.22/fs/reiserfs/dir.c linux-2.4.22-aclea/fs/reiserfs/dir.c
31 --- linux-2.4.22/fs/reiserfs/dir.c      2003-08-25 13:44:43.000000000 +0200
32 +++ linux-2.4.22-aclea/fs/reiserfs/dir.c        2003-09-12 17:19:29.000000000 +0200
33 @@ -110,6 +110,15 @@
34                     /* too big to send back to VFS */
35                     continue ;
36                 }
37 +
38 +                /* Ignore the .reiserfs_priv entry */
39 +               if (reiserfs_xattrs (inode->i_sb) && 
40 +                    !old_format_only(inode->i_sb) &&
41 +                    inode->i_sb->u.reiserfs_sb.priv_root &&
42 +                    inode->i_sb->u.reiserfs_sb.priv_root->d_inode &&
43 +                    deh_objectid (deh) == le32_to_cpu (INODE_PKEY(inode->i_sb->u.reiserfs_sb.priv_root->d_inode)->k_objectid))
44 +                  continue;
45 +
46                 d_off = deh_offset (deh);
47                 filp->f_pos = d_off ;
48                 d_ino = deh_objectid (deh);
49 diff -urN linux-2.4.22/fs/reiserfs/file.c linux-2.4.22-aclea/fs/reiserfs/file.c
50 --- linux-2.4.22/fs/reiserfs/file.c     2002-11-29 00:53:15.000000000 +0100
51 +++ linux-2.4.22-aclea/fs/reiserfs/file.c       2003-09-12 17:19:36.000000000 +0200
52 @@ -5,6 +5,8 @@
53  
54  #include <linux/sched.h>
55  #include <linux/reiserfs_fs.h>
56 +#include <linux/reiserfs_acl.h>
57 +#include <linux/reiserfs_xattr.h>
58  #include <linux/smp_lock.h>
59  
60  /*
61 @@ -90,45 +92,6 @@
62    return ( n_err < 0 ) ? -EIO : 0;
63  }
64  
65 -static int reiserfs_setattr(struct dentry *dentry, struct iattr *attr) {
66 -    struct inode *inode = dentry->d_inode ;
67 -    int error ;
68 -    if (attr->ia_valid & ATTR_SIZE) {
69 -       /* version 2 items will be caught by the s_maxbytes check
70 -       ** done for us in vmtruncate
71 -       */
72 -       if (get_inode_item_key_version(inode) == KEY_FORMAT_3_5 &&
73 -           attr->ia_size > MAX_NON_LFS)
74 -            return -EFBIG ;
75 -
76 -       /* fill in hole pointers in the expanding truncate case. */
77 -        if (attr->ia_size > inode->i_size) {
78 -           error = generic_cont_expand(inode, attr->ia_size) ;
79 -           if (inode->u.reiserfs_i.i_prealloc_count > 0) {
80 -               struct reiserfs_transaction_handle th ;
81 -               /* we're changing at most 2 bitmaps, inode + super */
82 -               journal_begin(&th, inode->i_sb, 4) ;
83 -               reiserfs_discard_prealloc (&th, inode);
84 -               journal_end(&th, inode->i_sb, 4) ;
85 -           }
86 -           if (error)
87 -               return error ;
88 -       }
89 -    }
90 -
91 -    if ((((attr->ia_valid & ATTR_UID) && (attr->ia_uid & ~0xffff)) ||
92 -        ((attr->ia_valid & ATTR_GID) && (attr->ia_gid & ~0xffff))) &&
93 -       (get_inode_sd_version (inode) == STAT_DATA_V1))
94 -               /* stat data of format v3.5 has 16 bit uid and gid */
95 -           return -EINVAL;
96 -
97 -    error = inode_change_ok(inode, attr) ;
98 -    if (!error)
99 -        inode_setattr(inode, attr) ;
100 -
101 -    return error ;
102 -}
103 -
104  struct file_operations reiserfs_file_operations = {
105      read:      generic_file_read,
106      write:     generic_file_write,
107 @@ -142,6 +105,11 @@
108  struct  inode_operations reiserfs_file_inode_operations = {
109      truncate:  reiserfs_vfs_truncate_file,
110      setattr:    reiserfs_setattr,
111 +    setxattr:   reiserfs_setxattr, 
112 +    getxattr:   reiserfs_getxattr, 
113 +    listxattr:   reiserfs_listxattr, 
114 +    removexattr:   reiserfs_removexattr, 
115 +    permission: reiserfs_permission,
116  };
117  
118  
119 diff -urN linux-2.4.22/fs/reiserfs/inode.c linux-2.4.22-aclea/fs/reiserfs/inode.c
120 --- linux-2.4.22/fs/reiserfs/inode.c    2003-08-25 13:44:43.000000000 +0200
121 +++ linux-2.4.22-aclea/fs/reiserfs/inode.c      2003-09-12 17:19:36.000000000 +0200
122 @@ -5,8 +5,11 @@
123  #include <linux/config.h>
124  #include <linux/sched.h>
125  #include <linux/reiserfs_fs.h>
126 +#include <linux/reiserfs_acl.h>
127 +#include <linux/reiserfs_xattr.h>
128  #include <linux/locks.h>
129  #include <linux/smp_lock.h>
130 +#include <linux/quotaops.h>
131  #include <asm/uaccess.h>
132  #include <asm/unaligned.h>
133  
134 @@ -37,6 +40,8 @@
135      if (INODE_PKEY(inode)->k_objectid != 0) { /* also handles bad_inode case */
136         down (&inode->i_sem); 
137  
138 +       reiserfs_delete_xattrs (inode);
139 +
140         journal_begin(&th, inode->i_sb, jbegin_count) ;
141         reiserfs_update_inode_transaction(inode) ;
142         windex = push_journal_writer("delete_inode") ;
143 @@ -206,6 +211,10 @@
144    struct super_block *s = th->t_super ;
145    int len = th->t_blocks_allocated ;
146  
147 +  /* we cannot restart while nested */
148 +  if (th->t_refcount > 1) {
149 +      return  ;
150 +  }
151    pathrelse(path) ;
152    reiserfs_update_sd(th, inode) ;
153    journal_end(th, s, len) ;
154 @@ -1016,7 +1025,7 @@
155         inode->i_op = &reiserfs_dir_inode_operations;
156         inode->i_fop = &reiserfs_dir_operations;
157      } else if (S_ISLNK (inode->i_mode)) {
158 -       inode->i_op = &page_symlink_inode_operations;
159 +       inode->i_op = &reiserfs_symlink_inode_operations;
160         inode->i_mapping->a_ops = &reiserfs_address_space_operations;
161      } else {
162         inode->i_blocks = 0;
163 @@ -1694,6 +1703,18 @@
164         goto out_inserted_sd;
165      }
166  
167 +    if (reiserfs_posixacl (inode->i_sb)) {
168 +        retval = reiserfs_inherit_default_acl (dir, dentry, inode);
169 +        if (retval) {
170 +            iput (inode);
171 +            err = retval;
172 +            reiserfs_check_path(&path_to_key) ;
173 +            goto out_inserted_sd;
174 +        }
175 +    } else if (inode->i_sb->s_flags & MS_POSIXACL) {
176 +        reiserfs_warning (inode->i_sb, "ACLs aren't enabled in the fs, but vfs thinks they are!\n");
177 +    }
178 +
179      insert_inode_hash (inode);
180      reiserfs_update_sd(th, inode) ;
181      reiserfs_check_path(&path_to_key) ;
182 @@ -2229,6 +2250,72 @@
183                               reiserfs_get_block_direct_io) ;
184  }
185  
186 +int reiserfs_setattr(struct dentry *dentry, struct iattr *attr) {
187 +    struct inode *inode = dentry->d_inode ;
188 +    int error ;
189 +    unsigned int ia_valid = attr->ia_valid;
190 +    if (attr->ia_valid & ATTR_SIZE) {
191 +       /* version 2 items will be caught by the s_maxbytes check
192 +       ** done for us in vmtruncate
193 +       */
194 +       if (get_inode_item_key_version(inode) == KEY_FORMAT_3_5 &&
195 +           attr->ia_size > MAX_NON_LFS)
196 +            return -EFBIG ;
197 +
198 +       /* fill in hole pointers in the expanding truncate case. */
199 +        if (attr->ia_size > inode->i_size) {
200 +           error = generic_cont_expand(inode, attr->ia_size) ;
201 +           if (inode->u.reiserfs_i.i_prealloc_count > 0) {
202 +               struct reiserfs_transaction_handle th ;
203 +               /* we're changing at most 2 bitmaps, inode + super */
204 +               journal_begin(&th, inode->i_sb, 4) ;
205 +               reiserfs_discard_prealloc (&th, inode);
206 +               journal_end(&th, inode->i_sb, 4) ;
207 +           }
208 +           if (error)
209 +               return error ;
210 +       }
211 +    }
212 +
213 +    if ((((attr->ia_valid & ATTR_UID) && (attr->ia_uid & ~0xffff)) ||
214 +        ((attr->ia_valid & ATTR_GID) && (attr->ia_gid & ~0xffff))) &&
215 +       (get_inode_sd_version (inode) == STAT_DATA_V1))
216 +               /* stat data of format v3.5 has 16 bit uid and gid */
217 +           return -EINVAL;
218 +
219 +    error = inode_change_ok(inode, attr) ;
220 +    if (!error) {
221 +       if ((ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) ||
222 +           (ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid)) {
223 +                if (!(attr->ia_valid & ATTR_SIZE))
224 +                    down (&inode->i_sem);
225 +                error = reiserfs_chown_xattrs (inode, attr);
226 +                if (!(attr->ia_valid & ATTR_SIZE))
227 +                    up (&inode->i_sem);
228 +
229 +#if defined(CONFIG_QUOTA)
230 +                if (!error)
231 +                    error = DQUOT_TRANSFER(inode, attr) ? -EDQUOT : 0;
232 +#endif
233 +        }
234 +        if (!error)
235 +            inode_setattr(inode, attr) ;
236 +    }
237 +
238 +
239 +    if (!error && reiserfs_posixacl (inode->i_sb)) {
240 +        if (attr->ia_valid & ATTR_MODE) {
241 +            if (!(attr->ia_valid & ATTR_SIZE))
242 +                down (&inode->i_sem);
243 +            error = reiserfs_acl_chmod (inode);
244 +            if (!(attr->ia_valid & ATTR_SIZE))
245 +                up (&inode->i_sem);
246 +        }
247 +    }
248 +
249 +    return error ;
250 +}
251 +
252  struct address_space_operations reiserfs_address_space_operations = {
253      writepage: reiserfs_writepage,
254      readpage: reiserfs_readpage, 
255 diff -urN linux-2.4.22/fs/reiserfs/journal.c linux-2.4.22-aclea/fs/reiserfs/journal.c
256 --- linux-2.4.22/fs/reiserfs/journal.c  2003-08-25 13:44:43.000000000 +0200
257 +++ linux-2.4.22-aclea/fs/reiserfs/journal.c    2003-09-12 17:04:51.000000000 +0200
258 @@ -2232,6 +2232,9 @@
259    time_t now = CURRENT_TIME ;
260    if (reiserfs_dont_log(th->t_super)) 
261      return 0 ;
262 +  /* cannot restart while nested */
263 +  if (th->t_refcount > 1)
264 +    return 0 ;
265    if ( SB_JOURNAL(th->t_super)->j_must_wait > 0 ||
266         (SB_JOURNAL(th->t_super)->j_len_alloc + new_alloc) >= SB_JOURNAL_MAX_BATCH(th->t_super) || 
267         atomic_read(&(SB_JOURNAL(th->t_super)->j_jlock)) ||
268 @@ -2287,6 +2290,9 @@
269      return 0 ;
270    }
271    PROC_INFO_INC( p_s_sb, journal.journal_being );
272 +  /* set here for journal_join */
273 +  th->t_refcount = 1; 
274 +  th->t_super = p_s_sb ;
275  
276  relock:
277    lock_journal(p_s_sb) ;
278 @@ -2343,9 +2349,7 @@
279    SB_JOURNAL(p_s_sb)->j_len_alloc += nblocks ;
280    th->t_blocks_logged = 0 ;
281    th->t_blocks_allocated = nblocks ;
282 -  th->t_super = p_s_sb ;
283    th->t_trans_id = SB_JOURNAL(p_s_sb)->j_trans_id ;
284 -  th->t_caller = "Unknown" ;
285    unlock_journal(p_s_sb) ;
286    p_s_sb->s_dirt = 1; 
287    return 0 ;
288 @@ -2353,11 +2357,47 @@
289  
290  
291  static int journal_join(struct reiserfs_transaction_handle *th, struct super_block *p_s_sb, unsigned long nblocks) {
292 +  struct reiserfs_transaction_handle *cur_th = current->journal_info;
293 +
294 +  /* this keeps do_journal_end from NULLing out the current->journal_info
295 +  ** pointer
296 +  */
297 +  th->t_handle_save = cur_th ;
298 +  if (cur_th && cur_th->t_refcount > 1) {
299 +      BUG() ;
300 +  }
301    return do_journal_begin_r(th, p_s_sb, nblocks, 1) ;
302  }
303  
304  int journal_begin(struct reiserfs_transaction_handle *th, struct super_block  * p_s_sb, unsigned long nblocks) {
305 -  return do_journal_begin_r(th, p_s_sb, nblocks, 0) ;
306 +    struct reiserfs_transaction_handle *cur_th = current->journal_info ;
307 +    int ret ;
308 +
309 +    th->t_handle_save = NULL ;
310 +    if (cur_th) {
311 +       /* we are nesting into the current transaction */
312 +       if (cur_th->t_super == p_s_sb) {
313 +             cur_th->t_refcount++ ;
314 +             memcpy(th, cur_th, sizeof(*th)); 
315 +             if (th->t_refcount <= 1) 
316 +                     printk("BAD: refcount <= 1, but journal_info != 0\n"); 
317 +             return 0;
318 +       } else {
319 +           /* we've ended up with a handle from a different filesystem.
320 +           ** save it and restore on journal_end.  This should never
321 +           ** really happen...
322 +           */
323 +           reiserfs_warning("clm-2100: nesting info a different FS\n") ;
324 +           th->t_handle_save = current->journal_info ;
325 +           current->journal_info = th;
326 +       }
327 +    } else {
328 +       current->journal_info = th;
329 +    }
330 +    ret = do_journal_begin_r(th, p_s_sb, nblocks, 0) ;
331 +    if (current->journal_info != th)
332 +        BUG() ;
333 +    return ret ;
334  }
335  
336  /* not used at all */
337 @@ -2497,7 +2537,23 @@
338  }
339  
340  int journal_end(struct reiserfs_transaction_handle *th, struct super_block *p_s_sb, unsigned long nblocks) {
341 -  return do_journal_end(th, p_s_sb, nblocks, 0) ;
342 +  if (!current->journal_info && th->t_refcount > 1) 
343 +    printk("REISER-NESTING: th NULL, refcount %d\n", th->t_refcount); 
344 +  if (th->t_refcount > 1) { 
345 +    struct reiserfs_transaction_handle *cur_th = current->journal_info ;
346 +
347 +    /* we aren't allowed to close a nested transaction on a different
348 +    ** filesystem from the one in the task struct
349 +    */
350 +    if (cur_th->t_super != th->t_super)
351 +      BUG() ;
352 +
353 +    th->t_refcount--;
354 +    memcpy(current->journal_info, th, sizeof(*th));
355 +    return 0; 
356 +  } else {
357 +    return do_journal_end(th, p_s_sb, nblocks, 0) ;
358 +  }
359  }
360  
361  /* removes from the current transaction, relsing and descrementing any counters.  
362 @@ -2600,6 +2656,10 @@
363  */
364  int journal_end_sync(struct reiserfs_transaction_handle *th, struct super_block *p_s_sb, unsigned long nblocks) {
365  
366 +  /* you can sync while nested, very, very bad */
367 +  if (th->t_refcount > 1) {
368 +    BUG() ;
369 +  }
370    if (SB_JOURNAL(p_s_sb)->j_len == 0) {
371      reiserfs_prepare_for_journal(p_s_sb, SB_BUFFER_WITH_SB(p_s_sb), 1) ;
372      journal_mark_dirty(th, p_s_sb, SB_BUFFER_WITH_SB(p_s_sb)) ;
373 @@ -3000,6 +3060,10 @@
374    int wait_on_commit = flags & WAIT ;
375    struct reiserfs_super_block *rs ; 
376  
377 +  if (th->t_refcount > 1)
378 +    BUG() ;
379 +
380 +  current->journal_info = th->t_handle_save;
381    if (reiserfs_dont_log(th->t_super)) {
382      return 0 ;
383    }
384 @@ -3037,8 +3101,11 @@
385    }
386  
387  #ifdef REISERFS_PREALLOCATE
388 +  /* quota ops might need to nest, setup the journal_info pointer for them */
389 +  current->journal_info = th ;
390    reiserfs_discard_all_prealloc(th); /* it should not involve new blocks into
391                                       * the transaction */
392 +  current->journal_info = th->t_handle_save ;
393  #endif
394    
395    rs = SB_DISK_SUPER_BLOCK(p_s_sb) ;
396 diff -urN linux-2.4.22/fs/reiserfs/namei.c linux-2.4.22-aclea/fs/reiserfs/namei.c
397 --- linux-2.4.22/fs/reiserfs/namei.c    2003-08-25 13:44:43.000000000 +0200
398 +++ linux-2.4.22-aclea/fs/reiserfs/namei.c      2003-09-12 17:19:36.000000000 +0200
399 @@ -6,6 +6,8 @@
400  #include <linux/sched.h>
401  #include <linux/bitops.h>
402  #include <linux/reiserfs_fs.h>
403 +#include <linux/reiserfs_acl.h>
404 +#include <linux/reiserfs_xattr.h>
405  #include <linux/smp_lock.h>
406  
407  #define INC_DIR_INODE_NLINK(i) if (i->i_nlink != 1) { i->i_nlink++; if (i->i_nlink >= REISERFS_LINK_MAX) i->i_nlink=1; }
408 @@ -323,10 +325,21 @@
409      retval = reiserfs_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &path_to_entry, &de);
410      pathrelse (&path_to_entry);
411      if (retval == NAME_FOUND) {
412 +        /* Hide the .reiserfs_priv dir */
413 +       if (reiserfs_xattrs (dir->i_sb) &&
414 +            !old_format_only(dir->i_sb) &&
415 +            dir->i_sb->u.reiserfs_sb.priv_root &&
416 +            dir->i_sb->u.reiserfs_sb.priv_root->d_inode &&
417 +            de.de_objectid == le32_to_cpu (INODE_PKEY(dir->i_sb->u.reiserfs_sb.priv_root->d_inode)->k_objectid)) {
418 +            return ERR_PTR (-EACCES);
419 +       }
420         inode = reiserfs_iget (dir->i_sb, (struct cpu_key *)&(de.de_dir_id));
421         if (!inode || IS_ERR(inode)) {
422             return ERR_PTR(-EACCES);
423          }
424 +        /* Propogate the priv_object flag so we know we're in the priv tree */
425 +        if (is_reiserfs_priv_object (dir))
426 +            inode->u.reiserfs_i.i_flags |= i_priv_object;
427      }
428      if ( retval == IO_ERROR ) {
429         return ERR_PTR(-EIO);
430 @@ -527,6 +540,7 @@
431      struct inode * inode;
432      int jbegin_count = JOURNAL_PER_BALANCE_CNT * 2 ;
433      struct reiserfs_transaction_handle th ;
434 +    int locked;
435  
436      if (!(inode = new_inode(dir->i_sb))) {
437         return -ENOMEM ;
438 @@ -535,8 +549,11 @@
439      if (retval)
440         return retval ;
441  
442 +    locked = reiserfs_cache_default_acl (dir);
443 +    if (locked)
444 +       reiserfs_write_lock_xattrs (dir->i_sb);
445 +
446      journal_begin(&th, dir->i_sb, jbegin_count) ;
447 -    th.t_caller = "create" ;
448      retval = reiserfs_new_inode (&th, dir, mode, 0, 0/*i_size*/, dentry, inode);
449      if (retval) {
450         goto out_failed ;
451 @@ -548,6 +565,9 @@
452  
453      retval = reiserfs_add_entry (&th, dir, dentry->d_name.name, dentry->d_name.len, 
454                                 inode, 1/*visible*/);
455 +    if (locked)
456 +       reiserfs_write_unlock_xattrs (dir->i_sb);
457 +
458      if (retval) {
459         inode->i_nlink--;
460         reiserfs_update_sd (&th, inode);
461 @@ -573,6 +593,7 @@
462      struct inode * inode;
463      struct reiserfs_transaction_handle th ;
464      int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3; 
465 +    int locked;
466  
467      if (!(inode = new_inode(dir->i_sb))) {
468         return -ENOMEM ;
469 @@ -581,9 +602,17 @@
470      if (retval)
471          return retval ;
472  
473 +    locked = reiserfs_cache_default_acl (dir);
474 +    if (locked)
475 +        reiserfs_write_lock_xattrs (inode->i_sb);
476 +
477      journal_begin(&th, dir->i_sb, jbegin_count) ;
478  
479      retval = reiserfs_new_inode(&th, dir, mode, 0, 0/*i_size*/, dentry, inode);
480 +
481 +    if (locked)
482 +       reiserfs_write_unlock_xattrs (inode->i_sb);
483 +
484      if (retval) {
485         goto out_failed; 
486      }
487 @@ -621,6 +650,7 @@
488      struct inode * inode;
489      struct reiserfs_transaction_handle th ;
490      int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3; 
491 +    int locked;
492  
493      mode = S_IFDIR | mode;
494      if (!(inode = new_inode(dir->i_sb))) {
495 @@ -630,6 +660,10 @@
496      if (retval)
497         return retval ;
498  
499 +    locked = reiserfs_cache_default_acl (dir);
500 +    if (locked)
501 +        reiserfs_write_lock_xattrs (inode->i_sb);
502 +
503      journal_begin(&th, dir->i_sb, jbegin_count) ;
504  
505      /* inc the link count now, so another writer doesn't overflow it while
506 @@ -645,6 +679,9 @@
507                                 old_format_only (dir->i_sb) ?
508                                 EMPTY_DIR_SIZE_V1 : EMPTY_DIR_SIZE,
509                                 dentry, inode) ;
510 +    if (locked)
511 +        reiserfs_write_unlock_xattrs (inode->i_sb);
512 +
513      if (retval) {
514         dir->i_nlink-- ;
515         goto out_failed ;
516 @@ -892,6 +929,8 @@
517      memcpy (name, symname, strlen (symname));
518      padd_item (name, item_len, strlen (symname));
519  
520 +    /* We would inherit the default ACL here, but symlinks don't get ACLs */
521 +
522      journal_begin(&th, parent_dir->i_sb, jbegin_count) ;
523  
524      retval = reiserfs_new_inode(&th, parent_dir, mode, name,
525 @@ -904,7 +943,7 @@
526      reiserfs_update_inode_transaction(inode) ;
527      reiserfs_update_inode_transaction(parent_dir) ;
528  
529 -    inode->i_op = &page_symlink_inode_operations;
530 +    inode->i_op = &reiserfs_symlink_inode_operations;
531      inode->i_mapping->a_ops = &reiserfs_address_space_operations;
532  
533      // must be sure this inode is written with this transaction
534 @@ -1277,5 +1316,25 @@
535      rmdir:     reiserfs_rmdir,
536      mknod:     reiserfs_mknod,
537      rename:    reiserfs_rename,
538 +    setattr:   reiserfs_setattr, 
539 +    setxattr:   reiserfs_setxattr, 
540 +    getxattr:   reiserfs_getxattr, 
541 +    listxattr:   reiserfs_listxattr, 
542 +    removexattr:   reiserfs_removexattr, 
543 +    permission: reiserfs_permission,
544  };
545  
546 +/*
547 + * symlink operations.. same as page_symlink_inode_operations, with xattr
548 + * stuff added
549 + */
550 +struct inode_operations reiserfs_symlink_inode_operations = {
551 +    readlink:       page_readlink,
552 +    follow_link:    page_follow_link,
553 +    setattr:        reiserfs_setattr,
554 +    setxattr:       reiserfs_setxattr,
555 +    getxattr:       reiserfs_getxattr,
556 +    listxattr:      reiserfs_listxattr,
557 +    removexattr:    reiserfs_removexattr,
558 +    permission: reiserfs_permission,
559 +};
560 diff -urN linux-2.4.22/fs/reiserfs/super.c linux-2.4.22-aclea/fs/reiserfs/super.c
561 --- linux-2.4.22/fs/reiserfs/super.c    2003-08-25 13:44:43.000000000 +0200
562 +++ linux-2.4.22-aclea/fs/reiserfs/super.c      2003-09-12 17:19:43.000000000 +0200
563 @@ -9,6 +9,9 @@
564  #include <linux/vmalloc.h>
565  #include <asm/uaccess.h>
566  #include <linux/reiserfs_fs.h>
567 +#include <linux/reiserfs_fs_sb.h>
568 +#include <linux/reiserfs_acl.h>
569 +#include <linux/reiserfs_xattr.h>
570  #include <linux/smp_lock.h>
571  #include <linux/locks.h>
572  #include <linux/init.h>
573 @@ -344,7 +346,17 @@
574  {
575    int i;
576    struct reiserfs_transaction_handle th ;
577 +
578 +  if (s->u.reiserfs_sb.xattr_root) {
579 +    d_invalidate (s->u.reiserfs_sb.xattr_root);
580 +    dput (s->u.reiserfs_sb.xattr_root);
581 +  }
582    
583 +  if (s->u.reiserfs_sb.priv_root) {
584 +    d_invalidate (s->u.reiserfs_sb.priv_root);
585 +    dput (s->u.reiserfs_sb.priv_root);
586 +  }
587 +
588    /* change file system state to current state if it was mounted with read-write permissions */
589    if (!(s->s_flags & MS_RDONLY)) {
590      journal_begin(&th, s, 10) ;
591 @@ -408,6 +420,22 @@
592      unlock_kernel() ;
593  }
594  
595 +static void reiserfs_clear_inode (struct inode *inode)
596 +{
597 +    struct posix_acl *acl;
598 +
599 +    acl = inode->u.reiserfs_i.i_acl_access;
600 +    if (acl && !IS_ERR (acl))
601 +        posix_acl_release (acl);
602 +    inode->u.reiserfs_i.i_acl_access = NULL;
603 +
604 +    acl = inode->u.reiserfs_i.i_acl_default;
605 +    if (acl && !IS_ERR (acl))
606 +        posix_acl_release (acl);
607 +    inode->u.reiserfs_i.i_acl_default = NULL;
608 +}
609 +
610 +
611  struct super_operations reiserfs_sops = 
612  {
613    read_inode: reiserfs_read_inode,
614 @@ -415,6 +443,7 @@
615    write_inode: reiserfs_write_inode,
616    dirty_inode: reiserfs_dirty_inode,
617    delete_inode: reiserfs_delete_inode,
618 +  clear_inode: reiserfs_clear_inode,
619    put_super: reiserfs_put_super,
620    write_super: reiserfs_write_super,
621    write_super_lockfs: reiserfs_write_super_lockfs,
622 @@ -616,6 +645,16 @@
623                 {"resize", 'r', 0, 0, 0},
624                 {"attrs", 0, 0, 1<<REISERFS_ATTRS, 0},
625                 {"noattrs", 0, 0, 0, 1<<REISERFS_ATTRS},
626 +#ifdef CONFIG_REISERFS_FS_XATTR
627 +# ifdef CONFIG_REISERFS_FS_XATTR_USER
628 +               {"user_xattr", 0, 0, REISERFS_XATTRS_USER},
629 +               {"nouser_xattr", 0, 0, REISERFS_NO_XATTRS_USER},
630 +# endif
631 +# ifdef CONFIG_REISERFS_FS_POSIX_ACL
632 +               {"acl", 0, 0, REISERFS_POSIXACL},
633 +               {"noacl", 0, 0, REISERFS_NO_POSIXACL},
634 +# endif
635 +#endif
636                 {NULL, 0, 0, 0, 0}
637      };
638         
639 @@ -692,6 +731,10 @@
640    safe_mask |= 1 << REISERFS_HASHED_RELOCATION;
641    safe_mask |= 1 << REISERFS_TEST4;
642    safe_mask |= 1 << REISERFS_ATTRS;
643 +  safe_mask |= 1 << REISERFS_XATTRS_USER;
644 +  safe_mask |= 1 << REISERFS_NO_XATTRS_USER;
645 +  safe_mask |= 1 << REISERFS_POSIXACL;
646 +  safe_mask |= 1 << REISERFS_NO_POSIXACL;
647  
648    /* Update the bitmask, taking care to keep
649     * the bits we're not allowed to change here */
650 @@ -706,6 +749,7 @@
651    }
652  
653    if (*mount_flags & MS_RDONLY) {
654 +    reiserfs_xattr_init (s, *mount_flags);
655      /* remount read-only */
656      if (s->s_flags & MS_RDONLY)
657        /* it is read-only already */
658 @@ -723,8 +767,10 @@
659      s->s_dirt = 0;
660    } else {
661      /* remount read-write */
662 -    if (!(s->s_flags & MS_RDONLY))
663 +    if (!(s->s_flags & MS_RDONLY)) {
664 +       reiserfs_xattr_init (s, *mount_flags);
665         return 0; /* We are read-write already */
666 +    }
667  
668      s->s_flags &= ~MS_RDONLY ; /* now it is safe to call journal_begin */
669      journal_begin(&th, s, 10) ;
670 @@ -743,8 +789,10 @@
671    SB_JOURNAL(s)->j_must_wait = 1 ;
672    journal_end(&th, s, 10) ;
673  
674 -  if (!( *mount_flags & MS_RDONLY ) )
675 +  if (!( *mount_flags & MS_RDONLY ) ) {
676      finish_unfinished( s );
677 +    reiserfs_xattr_init (s, *mount_flags);
678 +  }
679  
680    return 0;
681  }
682 @@ -1169,6 +1217,8 @@
683      s->u.reiserfs_sb.s_alloc_options.preallocmin = 4;
684      /* Preallocate by 8 blocks (9-1) at once */
685      s->u.reiserfs_sb.s_alloc_options.preallocsize = 9;
686 +    /* Initialize the rwsem for xattr dir */
687 +    init_rwsem(&s->u.reiserfs_sb.xattr_dir_sem);
688  
689      if (reiserfs_parse_options (s, (char *) data, &(s->u.reiserfs_sb.s_mount_opt), &blocks) == 0) {
690        return NULL;
691 @@ -1301,11 +1351,23 @@
692                 
693         journal_mark_dirty(&th, s, SB_BUFFER_WITH_SB (s));
694         journal_end(&th, s, 1) ;
695 -       
696 +
697 +       if (reiserfs_xattr_init (s, s->s_flags)) {
698 +           dput (s->s_root);
699 +           s->s_root = NULL;
700 +           goto error;
701 +       }
702 +
703         /* look for files which were to be removed in previous session */
704         finish_unfinished (s);
705  
706         s->s_dirt = 0;
707 +    } else {
708 +       if (reiserfs_xattr_init (s, s->s_flags)) {
709 +           dput (s->s_root);
710 +           s->s_root = NULL;
711 +           goto error;
712 +       }
713      }
714  
715      // mark hash in super block: it could be unset. overwrite should be ok
716 @@ -1364,10 +1426,29 @@
717  
718  static int __init init_reiserfs_fs (void)
719  {
720 +        int ret;
721         reiserfs_proc_info_global_init();
722         reiserfs_proc_register_global( "version", 
723                                        reiserfs_global_version_in_proc );
724 -        return register_filesystem(&reiserfs_fs_type);
725 +       ret = reiserfs_xattr_user_init ();
726 +       if (ret) goto failed_xattr_user_init;
727 +
728 +       ret = reiserfs_xattr_trusted_init();
729 +       if (ret) goto failed_xattr_trusted_init;
730 +
731 +       ret = reiserfs_xattr_posix_acl_init();
732 +       if (ret) goto failed_xattr_posix_acl_init;
733 +
734 +       return register_filesystem(&reiserfs_fs_type);
735 +
736 +failed_xattr_posix_acl_init:
737 +       reiserfs_xattr_trusted_exit();
738 +failed_xattr_trusted_init:
739 +       reiserfs_xattr_user_exit();
740 +failed_xattr_user_init:
741 +       reiserfs_proc_unregister_global( "version" );
742 +       reiserfs_proc_info_global_done();
743 +       return ret;
744  }
745  
746  MODULE_DESCRIPTION("ReiserFS journaled filesystem");
747 @@ -1377,6 +1458,9 @@
748  
749  static void __exit exit_reiserfs_fs(void)
750  {
751 +       reiserfs_xattr_posix_acl_exit ();
752 +       reiserfs_xattr_trusted_exit ();
753 +       reiserfs_xattr_user_exit ();
754         reiserfs_proc_unregister_global( "version" );
755         reiserfs_proc_info_global_done();
756          unregister_filesystem(&reiserfs_fs_type);
757 diff -urN linux-2.4.22/fs/reiserfs/xattr.c linux-2.4.22-aclea/fs/reiserfs/xattr.c
758 --- linux-2.4.22/fs/reiserfs/xattr.c    1970-01-01 01:00:00.000000000 +0100
759 +++ linux-2.4.22-aclea/fs/reiserfs/xattr.c      2003-09-12 17:19:37.000000000 +0200
760 @@ -0,0 +1,1266 @@
761 +/*
762 + * linux/fs/reiserfs/xattr.c
763 + *
764 + * Copyright (c) 2002 by Jeff Mahoney, <jeffm@suse.com>
765 + *
766 + */
767 +
768 +/*
769 + * In order to implement EA/ACLs in a clean, backwards compatible manner,
770 + * they are implemented as files in a "private" directory.
771 + * Each EA is in it's own file, with the directory layout like so (/ is assumed
772 + * to be relative to fs root). Inside the /.reiserfs_priv/xattrs directory,
773 + * directories named using the capital-hex form of the objectid and
774 + * generation number are used. Inside each directory are individual files
775 + * named with the name of the extended attribute.
776 + *
777 + * So, for objectid 12648430, we could have:
778 + * /.reiserfs_priv/xattrs/C0FFEE.0/system.posix_acl_access
779 + * /.reiserfs_priv/xattrs/C0FFEE.0/system.posix_acl_default
780 + * /.reiserfs_priv/xattrs/C0FFEE.0/user.Content-Type
781 + * .. or similar.
782 + *
783 + * The file contents are the text of the EA. The size is known based on the
784 + * stat data describing the file.
785 + *
786 + * In the case of system.posix_acl_access and system.posix_acl_default, since
787 + * these are special cases for filesystem ACLs, they are interpreted by the
788 + * kernel, in addition, they are negatively and positively cached and attached
789 + * to the inode so that unnecessary lookups are avoided.
790 + */
791 +
792 +#include <linux/reiserfs_fs.h>
793 +#include <linux/dcache.h>
794 +#include <linux/errno.h>
795 +#include <linux/fs.h>
796 +#include <linux/file.h>
797 +#include <linux/pagemap.h>
798 +#include <linux/xattr.h>
799 +#include <linux/reiserfs_xattr.h>
800 +#include <linux/mbcache.h>
801 +#include <asm/uaccess.h>
802 +#include <asm/checksum.h>
803 +#include <linux/smp_lock.h>
804 +#include <linux/stat.h>
805 +#include <asm/semaphore.h>
806 +
807 +#define FL_READONLY 128
808 +#define FL_DIR_SEM_HELD 256
809 +#define PRIVROOT_NAME ".reiserfs_priv"
810 +#define XAROOT_NAME   "xattrs"
811 +
812 +static struct reiserfs_xattr_handler *find_xattr_handler_prefix (const char *prefix);
813 +
814 +static struct dentry *
815 +create_xa_root (struct super_block *sb)
816 +{
817 +    struct dentry *privroot = dget (sb->u.reiserfs_sb.priv_root);
818 +    struct dentry *xaroot;
819 +
820 +    /* This needs to be created at mount-time */
821 +    if (!privroot)
822 +        return ERR_PTR(-EOPNOTSUPP);
823 +
824 +    xaroot = lookup_one_len (XAROOT_NAME, privroot, strlen (XAROOT_NAME));
825 +    if (IS_ERR (xaroot)) {
826 +        goto out;
827 +    } else if (!xaroot->d_inode) {
828 +        int err;
829 +        down (&privroot->d_inode->i_sem);
830 +        err = privroot->d_inode->i_op->mkdir (privroot->d_inode, xaroot, 0700);
831 +        up (&privroot->d_inode->i_sem);
832 +
833 +        if (err) {
834 +            dput (xaroot);
835 +            dput (privroot);
836 +            return ERR_PTR (err);
837 +        }
838 +        sb->u.reiserfs_sb.xattr_root = dget (xaroot);
839 +    }
840 +
841 +out:
842 +    dput (privroot);
843 +    return xaroot;
844 +}
845 +
846 +/* This will return a dentry, or error, refering to the xa root directory.
847 + * If the xa root doesn't exist yet, the dentry will be returned without
848 + * an associated inode. This dentry can be used with ->mkdir to create
849 + * the xa directory. */
850 +static struct dentry *
851 +__get_xa_root (struct super_block *s)
852 +{
853 +    struct dentry *privroot = dget (s->u.reiserfs_sb.priv_root);
854 +    struct dentry *xaroot = NULL;
855 +
856 +    if (IS_ERR (privroot) || !privroot)
857 +        return privroot;
858 +
859 +    xaroot = lookup_one_len (XAROOT_NAME, privroot, strlen (XAROOT_NAME));
860 +    if (IS_ERR (xaroot)) {
861 +        goto out;
862 +    } else if (!xaroot->d_inode) {
863 +        dput (xaroot);
864 +        xaroot = NULL;
865 +        goto out;
866 +    }
867 +
868 +    s->u.reiserfs_sb.xattr_root = dget (xaroot);
869 +
870 +out:
871 +    dput (privroot);
872 +    return xaroot;
873 +}
874 +
875 +/* Returns the dentry (or NULL) referring to the root of the extended
876 + * attribute directory tree. If it has already been retreived, it is used.
877 + * Otherwise, we attempt to retreive it from disk. It may also return
878 + * a pointer-encoded error.
879 + */
880 +static inline struct dentry *
881 +get_xa_root (struct super_block *s)
882 +{
883 +    struct dentry *dentry = s->u.reiserfs_sb.xattr_root;
884 +
885 +    if (!dentry)
886 +        dentry = __get_xa_root (s);
887 +    else
888 +        dget (dentry);
889 +    return dentry;
890 +}
891 +
892 +/* Same as above, but only returns a valid dentry or NULL */
893 +struct dentry *
894 +reiserfs_get_xa_root (struct super_block *sb)
895 +{
896 +    struct dentry *dentry;
897 +
898 +    dentry = get_xa_root (sb);
899 +    if (IS_ERR (dentry)) {
900 +        dentry = NULL;
901 +    } else if (dentry && !dentry->d_inode) {
902 +        dput (dentry);
903 +        dentry = NULL;
904 +    }
905 +
906 +    return dentry;
907 +}
908 +
909 +/* Opens the directory corresponding to the inode's extended attribute store.
910 + * If flags allow, the tree to the directory may be created. If creation is
911 + * prohibited, -ENODATA is returned. */
912 +static struct dentry *
913 +open_xa_dir (const struct inode *inode, int flags)
914 +{
915 +    struct dentry *xaroot, *xadir;
916 +    char namebuf[17];
917 +
918 +    xaroot = get_xa_root (inode->i_sb);
919 +    if (IS_ERR (xaroot)) {
920 +        return xaroot;
921 +    } else if (!xaroot) {
922 +        if (flags == 0 || flags & XATTR_CREATE) {
923 +            xaroot = create_xa_root (inode->i_sb);
924 +            if (IS_ERR (xaroot))
925 +                return xaroot;
926 +        }
927 +        if (!xaroot)
928 +            return ERR_PTR (-ENODATA);
929 +    }
930 +
931 +    /* ok, we have xaroot open */
932 +
933 +    snprintf (namebuf, sizeof (namebuf), "%X.%X",
934 +              le32_to_cpu (INODE_PKEY (inode)->k_objectid),
935 +              inode->i_generation);
936 +    xadir = lookup_one_len (namebuf, xaroot, strlen (namebuf));
937 +    if (IS_ERR (xadir)) {
938 +        dput (xaroot);
939 +        return xadir;
940 +    }
941 +    
942 +    if (!xadir->d_inode) {
943 +        int err;
944 +        if (flags == 0 || flags & XATTR_CREATE) {
945 +            /* Although there is nothing else trying to create this directory,
946 +             * another directory with the same hash may be created, so we need
947 +             * to protect against that */
948 +            err = xaroot->d_inode->i_op->mkdir (xaroot->d_inode, xadir, 0700);
949 +            if (err) {
950 +                dput (xaroot);
951 +                dput (xadir);
952 +                return ERR_PTR (err);
953 +            }
954 +        }
955 +        if (!xadir->d_inode) {
956 +            dput (xaroot);
957 +            dput (xadir);
958 +            return ERR_PTR (-ENODATA);
959 +        }
960 +    }
961 +
962 +    dput (xaroot);
963 +    return xadir;
964 +}
965 +
966 +/* Returns a dentry corresponding to a specific extended attribute file
967 + * for the inode. If flags allow, the file is created. Otherwise, a
968 + * valid or negative dentry, or an error is returned. */
969 +static struct dentry *
970 +get_xa_file_dentry (const struct inode *inode, const char *name, int flags)
971 +{
972 +    struct dentry *xadir, *xafile;
973 +    int err = 0;
974 +
975 +    xadir = open_xa_dir (inode, flags);
976 +    if (IS_ERR (xadir)) {
977 +        return ERR_PTR (PTR_ERR (xadir));
978 +    } else if (xadir && !xadir->d_inode) {
979 +        dput (xadir);
980 +        return ERR_PTR (-ENODATA);
981 +    }
982 +
983 +    xafile = lookup_one_len (name, xadir, strlen (name));
984 +    if (IS_ERR (xafile)) {
985 +        dput (xadir);
986 +        return ERR_PTR (PTR_ERR (xafile));
987 +    }
988 +
989 +    if (xafile->d_inode) { /* file exists */
990 +        if (flags & XATTR_CREATE) {
991 +            err = -EEXIST;
992 +            dput (xafile);
993 +            goto out;
994 +        }
995 +    } else if (flags & XATTR_REPLACE || flags & FL_READONLY) {
996 +        goto out;
997 +    } else {
998 +        /* inode->i_sem is down, so nothing else can try to create
999 +         * the same xattr */
1000 +        err = xadir->d_inode->i_op->create (xadir->d_inode, xafile,
1001 +                                            0700|S_IFREG);
1002 +
1003 +        if (err) {
1004 +            dput (xafile);
1005 +            goto out;
1006 +        }
1007 +    }
1008 +
1009 +out:
1010 +    dput (xadir);
1011 +    if (err)
1012 +        xafile = ERR_PTR (err);
1013 +    return xafile;
1014 +}
1015 +
1016 +
1017 +/* Opens a file pointer to the attribute associated with inode */
1018 +static struct file *
1019 +open_xa_file (const struct inode *inode, const char *name, int flags)
1020 +{
1021 +    struct dentry *xafile;
1022 +    struct file *fp;
1023 +
1024 +    xafile = get_xa_file_dentry (inode, name, flags);
1025 +    if (IS_ERR (xafile))
1026 +        return ERR_PTR (PTR_ERR (xafile));
1027 +    else if (!xafile->d_inode) {
1028 +        dput (xafile);
1029 +        return ERR_PTR (-ENODATA);
1030 +    }
1031 +
1032 +    fp = dentry_open (xafile, NULL, O_RDWR);
1033 +    /* dentry_open dputs the dentry if it fails */
1034 +
1035 +    return fp;
1036 +}
1037 +
1038 +
1039 +/*
1040 + * this is very similar to fs/reiserfs/dir.c:reiserfs_readdir, but
1041 + * we need to drop the path before calling the filldir struct.  That
1042 + * would be a big performance hit to the non-xattr case, so I've copied
1043 + * the whole thing for now. --clm
1044 + *
1045 + * the big difference is that I go backwards through the directory, 
1046 + * and don't mess with f->f_pos, but the idea is the same.  Do some
1047 + * action on each and every entry in the directory.
1048 + *
1049 + * we're called with i_sem held, so there are no worries about the directory
1050 + * changing underneath us.
1051 + */
1052 +static int __xattr_readdir(struct file * filp, void * dirent, filldir_t filldir)
1053 +{
1054 +    struct inode *inode = filp->f_dentry->d_inode;
1055 +    struct cpu_key pos_key;    /* key of current position in the directory (key of directory entry) */
1056 +    INITIALIZE_PATH (path_to_entry);
1057 +    struct buffer_head * bh;
1058 +    int entry_num;
1059 +    struct item_head * ih, tmp_ih;
1060 +    int search_res;
1061 +    char * local_buf;
1062 +    loff_t next_pos;
1063 +    char small_buf[32] ; /* avoid kmalloc if we can */
1064 +    struct reiserfs_de_head *deh;
1065 +    int d_reclen;
1066 +    char * d_name;
1067 +    off_t d_off;
1068 +    ino_t d_ino;
1069 +    struct reiserfs_dir_entry de;
1070 +
1071 +
1072 +    /* form key for search the next directory entry using f_pos field of
1073 +       file structure */
1074 +    next_pos = max_reiserfs_offset(inode);
1075 +
1076 +    while (1) {
1077 +research:
1078 +       if (next_pos <= DOT_DOT_OFFSET)
1079 +           break;
1080 +       make_cpu_key (&pos_key, inode, next_pos, TYPE_DIRENTRY, 3);
1081 +
1082 +       search_res = search_by_entry_key(inode->i_sb, &pos_key, &path_to_entry, &de);
1083 +       if (search_res == IO_ERROR) {
1084 +           // FIXME: we could just skip part of directory which could
1085 +           // not be read
1086 +           pathrelse(&path_to_entry);
1087 +           return -EIO;
1088 +       }
1089 +
1090 +       if (search_res == NAME_NOT_FOUND)
1091 +           de.de_entry_num--;
1092 +
1093 +       set_de_name_and_namelen(&de);
1094 +       entry_num = de.de_entry_num;
1095 +       deh = &(de.de_deh[entry_num]);
1096 +
1097 +       bh = de.de_bh;
1098 +       ih = de.de_ih;
1099 +
1100 +       if (!is_direntry_le_ih(ih)) {
1101 +reiserfs_warning(inode->i_sb, "not direntry %h\n", ih);
1102 +           break;
1103 +        }
1104 +       copy_item_head(&tmp_ih, ih);
1105 +               
1106 +       /* we must have found item, that is item of this directory, */
1107 +       RFALSE( COMP_SHORT_KEYS (&(ih->ih_key), &pos_key),
1108 +               "vs-9000: found item %h does not match to dir we readdir %K",
1109 +               ih, &pos_key);
1110 +
1111 +       if (deh_offset(deh) <= DOT_DOT_OFFSET) {
1112 +           break;
1113 +       }
1114 +
1115 +       /* look for the previous entry in the directory */
1116 +       next_pos = deh_offset (deh) - 1;
1117 +
1118 +       if (!de_visible (deh))
1119 +           /* it is hidden entry */
1120 +           continue;
1121 +
1122 +       d_reclen = entry_length(bh, ih, entry_num);
1123 +       d_name = B_I_DEH_ENTRY_FILE_NAME (bh, ih, deh);
1124 +       d_off = deh_offset (deh);
1125 +       d_ino = deh_objectid (deh);
1126 +
1127 +       if (!d_name[d_reclen - 1])
1128 +           d_reclen = strlen (d_name);
1129 +
1130 +       if (d_reclen > REISERFS_MAX_NAME(inode->i_sb->s_blocksize)){
1131 +           /* too big to send back to VFS */
1132 +           continue ;
1133 +       }
1134 +
1135 +        /* Ignore the .reiserfs_priv entry */
1136 +        if (reiserfs_xattrs (inode->i_sb) && 
1137 +            !old_format_only(inode->i_sb) &&
1138 +            deh_objectid (deh) == le32_to_cpu (INODE_PKEY(inode->i_sb->u.reiserfs_sb.priv_root->d_inode)->k_objectid))
1139 +          continue;
1140 +
1141 +       if (d_reclen <= 32) {
1142 +         local_buf = small_buf ;
1143 +       } else {
1144 +           local_buf = reiserfs_kmalloc(d_reclen, GFP_NOFS, inode->i_sb) ;
1145 +           if (!local_buf) {
1146 +               pathrelse (&path_to_entry);
1147 +               return -ENOMEM ;
1148 +           }
1149 +           if (item_moved (&tmp_ih, &path_to_entry)) {
1150 +               reiserfs_kfree(local_buf, d_reclen, inode->i_sb) ;
1151 +
1152 +               /* sigh, must retry.  Do this same offset again */
1153 +               next_pos = d_off;
1154 +               goto research;
1155 +           }
1156 +       }
1157 +
1158 +       // Note, that we copy name to user space via temporary
1159 +       // buffer (local_buf) because filldir will block if
1160 +       // user space buffer is swapped out. At that time
1161 +       // entry can move to somewhere else
1162 +       memcpy (local_buf, d_name, d_reclen);
1163 +
1164 +       /* the filldir function might need to start transactions,
1165 +        * or do who knows what.  Release the path now that we've
1166 +        * copied all the important stuff out of the deh
1167 +        */
1168 +       pathrelse (&path_to_entry);
1169 +
1170 +       if (filldir (dirent, local_buf, d_reclen, d_off, d_ino, 
1171 +                    DT_UNKNOWN) < 0) {
1172 +           if (local_buf != small_buf) {
1173 +               reiserfs_kfree(local_buf, d_reclen, inode->i_sb) ;
1174 +           }
1175 +           goto end;
1176 +       }
1177 +       if (local_buf != small_buf) {
1178 +           reiserfs_kfree(local_buf, d_reclen, inode->i_sb) ;
1179 +       }
1180 +    } /* while */
1181 +
1182 +end:
1183 +    pathrelse (&path_to_entry);
1184 +    return 0;
1185 +}
1186 +
1187 +/* 
1188 + * this could be done with dedicated readdir ops for the xattr files,
1189 + * but I want to get something working asap
1190 + * this is stolen from vfs_readdir
1191 + *
1192 + */
1193 +static
1194 +int xattr_readdir(struct file *file, filldir_t filler, void *buf)
1195 +{
1196 +        struct inode *inode = file->f_dentry->d_inode;
1197 +        int res = -ENOTDIR;
1198 +        if (!file->f_op || !file->f_op->readdir)
1199 +                goto out;
1200 +        down(&inode->i_sem);
1201 +        down(&inode->i_zombie);
1202 +        res = -ENOENT;
1203 +        if (!IS_DEADDIR(inode)) {
1204 +                lock_kernel();
1205 +                res = __xattr_readdir(file, buf, filler);
1206 +                unlock_kernel();
1207 +        }
1208 +        up(&inode->i_zombie);
1209 +        up(&inode->i_sem);
1210 +out:
1211 +        return res;
1212 +}
1213 +
1214 +
1215 +/* Internal operations on file data */
1216 +static inline void
1217 +reiserfs_put_page(struct page *page)
1218 +{
1219 +        kunmap(page);
1220 +        page_cache_release(page);
1221 +}
1222 +
1223 +static struct page *
1224 +reiserfs_get_page(struct inode *dir, unsigned long n)
1225 +{
1226 +        struct address_space *mapping = dir->i_mapping; 
1227 +        struct page *page;
1228 +        /* We can deadlock if we try to free dentries,
1229 +           and an unlink/rmdir has just occured - GFP_NOFS avoids this */
1230 +        mapping->gfp_mask = GFP_NOFS;
1231 +        page = read_cache_page (mapping, n,
1232 +                                (filler_t*)mapping->a_ops->readpage, NULL);
1233 +        if (!IS_ERR(page)) {
1234 +                wait_on_page(page);
1235 +                kmap(page);
1236 +                if (!Page_Uptodate(page))
1237 +                        goto fail;
1238 +
1239 +                if (PageError(page))
1240 +                        goto fail;
1241 +        }
1242 +        return page;
1243 +
1244 +fail:
1245 +        reiserfs_put_page(page);
1246 +        return ERR_PTR(-EIO);
1247 +}
1248 +
1249 +static inline __u32
1250 +xattr_hash (const char *msg, int len)
1251 +{
1252 +    return csum_partial (msg, len, 0);
1253 +}
1254 +
1255 +/* Generic extended attribute operations that can be used by xa plugins */
1256 +
1257 +/*
1258 + * inode->i_sem: down
1259 + */
1260 +int
1261 +reiserfs_xattr_set (struct inode *inode, const char *name, const void *buffer,
1262 +                    size_t buffer_size, int flags)
1263 +{
1264 +    int err = 0;
1265 +    struct file *fp;
1266 +    struct page *page;
1267 +    char *data;
1268 +    struct address_space *mapping;
1269 +    size_t file_pos = 0;
1270 +    size_t buffer_pos = 0;
1271 +    struct inode *xinode;
1272 +    struct iattr newattrs;
1273 +    __u32 xahash = 0;
1274 +
1275 +    if (get_inode_sd_version (inode) == STAT_DATA_V1)
1276 +        return -EOPNOTSUPP;
1277 +
1278 +    /* Empty xattrs are ok, they're just empty files, no hash */
1279 +    if (buffer && buffer_size)
1280 +        xahash = xattr_hash (buffer, buffer_size);
1281 +
1282 +open_file:
1283 +    fp = open_xa_file (inode, name, flags);
1284 +    if (IS_ERR (fp)) {
1285 +        err = PTR_ERR (fp);
1286 +        goto out;
1287 +    }
1288 +
1289 +    xinode = fp->f_dentry->d_inode;
1290 +
1291 +    /* we need to copy it off.. */
1292 +    if (xinode->i_nlink > 1) {
1293 +       fput(fp);
1294 +        err = reiserfs_xattr_del (inode, name);
1295 +        if (err < 0)
1296 +            goto out;
1297 +        /* We just killed the old one, we're not replacing anymore */
1298 +        if (flags & XATTR_REPLACE)
1299 +            flags &= ~XATTR_REPLACE;
1300 +        goto open_file;
1301 +    }
1302 +
1303 +    /* Resize it so we're ok to write there */
1304 +    newattrs.ia_size = buffer_size;
1305 +    newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
1306 +    down (&xinode->i_sem);
1307 +    err = notify_change(fp->f_dentry, &newattrs);
1308 +    if (err)
1309 +        goto out_filp;
1310 +
1311 +    mapping = xinode->i_mapping;
1312 +    while (buffer_pos < buffer_size || buffer_pos == 0) {
1313 +        size_t chunk;
1314 +        size_t skip = 0;
1315 +        size_t page_offset = (file_pos & (PAGE_CACHE_SIZE - 1));
1316 +        if (buffer_size - buffer_pos > PAGE_CACHE_SIZE)
1317 +            chunk = PAGE_CACHE_SIZE;
1318 +        else
1319 +            chunk = buffer_size - buffer_pos;
1320 +
1321 +        page = reiserfs_get_page (xinode, file_pos >> PAGE_CACHE_SHIFT);
1322 +        if (IS_ERR (page)) {
1323 +            err = PTR_ERR (page);
1324 +            goto out_filp;
1325 +        }
1326 +
1327 +        lock_page (page);
1328 +        data = page_address (page);
1329 +
1330 +        if (file_pos == 0) {
1331 +            struct reiserfs_xattr_header *rxh;
1332 +            skip = file_pos = sizeof (struct reiserfs_xattr_header);
1333 +            if (chunk + skip > PAGE_CACHE_SIZE)
1334 +                chunk = PAGE_CACHE_SIZE - skip;
1335 +            rxh = (struct reiserfs_xattr_header *)data;
1336 +            rxh->h_magic = cpu_to_le32 (REISERFS_XATTR_MAGIC);
1337 +            rxh->h_hash = cpu_to_le32 (xahash);
1338 +        }
1339 +
1340 +        err = mapping->a_ops->prepare_write (fp, page, page_offset,
1341 +                                             page_offset + chunk + skip);
1342 +        if (!err) {
1343 +           if (buffer)
1344 +               memcpy (data + skip, buffer + buffer_pos, chunk);
1345 +            err = mapping->a_ops->commit_write (fp, page, page_offset,
1346 +                                                page_offset + chunk + skip);
1347 +       }
1348 +        UnlockPage (page);
1349 +        reiserfs_put_page (page);
1350 +        buffer_pos += chunk;
1351 +        file_pos += chunk;
1352 +        skip = 0;
1353 +        if (err || buffer_size == 0 || !buffer)
1354 +            break;
1355 +    }
1356 +
1357 +out_filp:
1358 +    up (&xinode->i_sem);
1359 +    fput(fp);
1360 +
1361 +out:
1362 +    return err;
1363 +}
1364 +
1365 +/*
1366 + * inode->i_sem: down
1367 + */
1368 +int
1369 +reiserfs_xattr_get (const struct inode *inode, const char *name, void *buffer,
1370 +                    size_t buffer_size)
1371 +{
1372 +    ssize_t err = 0;
1373 +    struct file *fp;
1374 +    size_t isize;
1375 +    size_t file_pos = 0;
1376 +    size_t buffer_pos = 0;
1377 +    struct page *page;
1378 +    struct inode *xinode;
1379 +    __u32 hash = 0;
1380 +
1381 +    /* We can't have xattrs attached to v1 items since they don't have
1382 +     * generation numbers */
1383 +    if (get_inode_sd_version (inode) == STAT_DATA_V1)
1384 +        return -EOPNOTSUPP;
1385 +
1386 +    fp = open_xa_file (inode, name, FL_READONLY);
1387 +    if (IS_ERR (fp)) {
1388 +        err = PTR_ERR (fp);
1389 +        goto out;
1390 +    }
1391 +
1392 +    xinode = fp->f_dentry->d_inode;
1393 +    isize = xinode->i_size;
1394 +
1395 +    /* Just return the size needed */
1396 +    if (buffer == NULL) {
1397 +        err = isize - sizeof (struct reiserfs_xattr_header);
1398 +        goto out_dput;
1399 +    }
1400 +
1401 +    if (buffer_size < isize - sizeof (struct reiserfs_xattr_header)) {
1402 +        err = -ERANGE;
1403 +        goto out_dput;
1404 +    }
1405 +    
1406 +    while (file_pos < isize) {
1407 +        size_t chunk;
1408 +        char *data;
1409 +        size_t skip = 0;
1410 +        if (isize - file_pos > PAGE_CACHE_SIZE)
1411 +            chunk = PAGE_CACHE_SIZE;
1412 +        else
1413 +            chunk = isize - file_pos;
1414 +
1415 +        page = reiserfs_get_page (xinode, file_pos >> PAGE_CACHE_SHIFT);
1416 +        if (IS_ERR (page)) {
1417 +            err = PTR_ERR (page);
1418 +            goto out_dput;
1419 +        }
1420 +
1421 +        lock_page (page);
1422 +        data = page_address (page);
1423 +        if (file_pos == 0) {
1424 +            struct reiserfs_xattr_header *rxh =
1425 +                                        (struct reiserfs_xattr_header *)data;
1426 +            skip = file_pos = sizeof (struct reiserfs_xattr_header);
1427 +            chunk -= skip;
1428 +            /* Magic doesn't match up.. */
1429 +            if (rxh->h_magic != cpu_to_le32 (REISERFS_XATTR_MAGIC)) {
1430 +                UnlockPage (page);
1431 +                reiserfs_put_page (page);
1432 +                err = -EIO;
1433 +                goto out_dput;
1434 +            }
1435 +            hash = le32_to_cpu (rxh->h_hash);
1436 +        }
1437 +        memcpy (buffer + buffer_pos, data + skip, chunk);
1438 +        UnlockPage (page);
1439 +        reiserfs_put_page (page);
1440 +        file_pos += chunk;
1441 +        buffer_pos += chunk;
1442 +        skip = 0;
1443 +    }
1444 +    err = isize - sizeof (struct reiserfs_xattr_header);
1445 +
1446 +    if (xattr_hash (buffer, isize - sizeof (struct reiserfs_xattr_header)) != hash)
1447 +        err = -EIO;
1448 +
1449 +out_dput:
1450 +    fput(fp);
1451 +
1452 +out:
1453 +    return err;
1454 +}
1455 +
1456 +static int
1457 +__reiserfs_xattr_del (struct dentry *xadir, const char *name, int namelen)
1458 +{
1459 +    struct dentry *file;
1460 +    struct inode *dir = xadir->d_inode;
1461 +    int err = 0;
1462 +
1463 +    file = lookup_one_len (name, xadir, namelen);
1464 +    if (IS_ERR (file)) {
1465 +        err = PTR_ERR (file);
1466 +        goto out;
1467 +    } else if (!file->d_inode) {
1468 +        err = -ENODATA;
1469 +        goto out_file;
1470 +    }
1471 +
1472 +    /* Skip directories.. */
1473 +    if (S_ISDIR (file->d_inode->i_mode))
1474 +        goto out_file;
1475 +
1476 +    if (!is_reiserfs_priv_object (file->d_inode)) {
1477 +        reiserfs_warning (file->d_inode->i_sb, "trying to delete objectid %08x, which isn't an xattr!\n", le32_to_cpu (INODE_PKEY (file->d_inode)->k_objectid));
1478 +        dput (file);
1479 +        return -EIO;
1480 +    }
1481 +
1482 +    err = dir->i_op->unlink (dir, file);
1483 +    if (!err)
1484 +        d_delete (file);
1485 +
1486 +out_file:
1487 +    dput (file);
1488 +
1489 +out:
1490 +    return err;
1491 +}
1492 +
1493 +
1494 +int
1495 +reiserfs_xattr_del (struct inode *inode, const char *name)
1496 +{
1497 +    struct dentry *dir;
1498 +    int err;
1499 +
1500 +    dir = open_xa_dir (inode, FL_READONLY);
1501 +    if (IS_ERR (dir)) {
1502 +        err = PTR_ERR (dir);
1503 +        goto out;
1504 +    }
1505 +
1506 +    err = __reiserfs_xattr_del (dir, name, strlen (name));
1507 +    dput (dir);
1508 +
1509 +out:
1510 +    return err;
1511 +}
1512 +
1513 +/* The following are side effects of other operations that aren't explicitly
1514 + * modifying extended attributes. This includes operations such as permissions
1515 + * or ownership changes, object deletions, etc. */
1516
1517 +static int
1518 +reiserfs_delete_xattrs_filler (void *buf, const char *name, int namelen,
1519 +                               loff_t offset, ino_t ino, unsigned int d_type)
1520 +{
1521 +    struct dentry *xadir = (struct dentry *)buf;
1522 +
1523 +    return __reiserfs_xattr_del (xadir, name, namelen);
1524 +
1525 +}
1526 +
1527 +int
1528 +reiserfs_delete_xattrs (struct inode *inode)
1529 +{
1530 +    struct file *fp;
1531 +    struct dentry *dir, *root;
1532 +    int err = 0;
1533 +
1534 +    /* Skip out, an xattr has no xattrs associated with it */
1535 +    if (is_reiserfs_priv_object (inode) ||
1536 +        get_inode_sd_version (inode) == STAT_DATA_V1 || 
1537 +        !reiserfs_xattrs(inode->i_sb))
1538 +    {
1539 +        return 0;
1540 +    }
1541 +    reiserfs_read_lock_xattrs (inode->i_sb);
1542 +    dir = open_xa_dir (inode, FL_READONLY);
1543 +    reiserfs_read_unlock_xattrs (inode->i_sb);
1544 +    if (IS_ERR (dir)) {
1545 +        err = PTR_ERR (dir);
1546 +        goto out;
1547 +    } else if (!dir->d_inode) {
1548 +        dput (dir);
1549 +        return 0;
1550 +    }
1551 +
1552 +    fp = dentry_open (dir, NULL, O_RDWR);
1553 +    if (IS_ERR (fp)) {
1554 +        err = PTR_ERR (fp);
1555 +        /* dentry_open dputs the dentry if it fails */
1556 +        goto out;
1557 +    }
1558 +
1559 +    lock_kernel ();
1560 +    err = xattr_readdir (fp, reiserfs_delete_xattrs_filler, dir);
1561 +    if (err) {
1562 +        unlock_kernel ();
1563 +        goto out_dir;
1564 +    }
1565 +
1566 +    /* Leftovers besides . and .. -- that's not good. */
1567 +    if (dir->d_inode->i_nlink <= 2) {
1568 +        root = get_xa_root (inode->i_sb);
1569 +        reiserfs_write_lock_xattrs (inode->i_sb);
1570 +        err = vfs_rmdir (root->d_inode, dir);
1571 +        reiserfs_write_unlock_xattrs (inode->i_sb);
1572 +        dput (root);
1573 +    } else {
1574 +        reiserfs_warning (inode->i_sb, "Couldn't remove all entries in directory\n");
1575 +    }
1576 +    unlock_kernel ();
1577 +
1578 +out_dir:
1579 +    fput(fp);
1580 +
1581 +out:
1582 +    return err;
1583 +}
1584 +
1585 +struct reiserfs_chown_buf {
1586 +    struct inode *inode;
1587 +    struct dentry *xadir;
1588 +    struct iattr *attrs;
1589 +};
1590 +
1591 +/* XXX: If there is a better way to do this, I'd love to hear about it */
1592 +static int
1593 +reiserfs_chown_xattrs_filler (void *buf, const char *name, int namelen,
1594 +                               loff_t offset, ino_t ino, unsigned int d_type)
1595 +{
1596 +    struct reiserfs_chown_buf *chown_buf = (struct reiserfs_chown_buf *)buf;
1597 +    struct dentry *xafile, *xadir = chown_buf->xadir;
1598 +    struct iattr *attrs = chown_buf->attrs;
1599 +    int err = 0;
1600 +
1601 +    xafile = lookup_one_len (name, xadir, namelen);
1602 +    if (IS_ERR (xafile))
1603 +        return PTR_ERR (xafile);
1604 +    else if (!xafile->d_inode) {
1605 +        dput (xafile);
1606 +        return -ENODATA;
1607 +    }
1608 +
1609 +    if (!S_ISDIR (xafile->d_inode->i_mode))
1610 +        err = notify_change (xafile, attrs);
1611 +    dput (xafile);
1612 +
1613 +    return err;
1614 +}
1615 +
1616 +int
1617 +reiserfs_chown_xattrs (struct inode *inode, struct iattr *attrs)
1618 +{
1619 +    struct file *fp;
1620 +    struct dentry *dir;
1621 +    int err = 0;
1622 +    struct reiserfs_chown_buf buf;
1623 +    unsigned int ia_valid = attrs->ia_valid;
1624 +
1625 +    /* Skip out, an xattr has no xattrs associated with it */
1626 +    if (is_reiserfs_priv_object (inode) ||
1627 +        get_inode_sd_version (inode) == STAT_DATA_V1 || 
1628 +        !reiserfs_xattrs(inode->i_sb))
1629 +    {
1630 +        return 0;
1631 +    }
1632 +    reiserfs_read_lock_xattrs (inode->i_sb);
1633 +    dir = open_xa_dir (inode, FL_READONLY);
1634 +    reiserfs_read_unlock_xattrs (inode->i_sb);
1635 +    if (IS_ERR (dir)) {
1636 +        if (PTR_ERR (dir) != -ENODATA)
1637 +            err = PTR_ERR (dir);
1638 +        goto out;
1639 +    } else if (!dir->d_inode) {
1640 +        dput (dir);
1641 +        goto out;
1642 +    }
1643 +
1644 +    fp = dentry_open (dir, NULL, O_RDWR);
1645 +    if (IS_ERR (fp)) {
1646 +        err = PTR_ERR (fp);
1647 +        /* dentry_open dputs the dentry if it fails */
1648 +        goto out;
1649 +    }
1650 +
1651 +    lock_kernel ();
1652 +
1653 +    attrs->ia_valid &= (ATTR_UID | ATTR_GID | ATTR_CTIME);
1654 +    buf.xadir = dir;
1655 +    buf.attrs = attrs;
1656 +    buf.inode = inode;
1657 +
1658 +    err = xattr_readdir (fp, reiserfs_chown_xattrs_filler, &buf);
1659 +    if (err) {
1660 +        unlock_kernel ();
1661 +        goto out_dir;
1662 +    }
1663 +
1664 +    err = notify_change (dir, attrs);
1665 +    unlock_kernel ();
1666 +
1667 +out_dir:
1668 +    fput(fp);
1669 +
1670 +out:
1671 +    attrs->ia_valid = ia_valid;
1672 +    return err;
1673 +}
1674 +
1675 +
1676 +/* Actual operations that are exported to VFS-land */
1677 +
1678 +/*
1679 + * Inode operation getxattr()
1680 + * dentry->d_inode->i_sem down
1681 + * BKL held [before 2.5.x]
1682 + */
1683 +ssize_t
1684 +reiserfs_getxattr (struct dentry *dentry, const char *name, void *buffer,
1685 +                   size_t size)
1686 +{
1687 +    struct reiserfs_xattr_handler *xah = find_xattr_handler_prefix (name);
1688 +    int err;
1689 +
1690 +    if (!xah || !reiserfs_xattrs(dentry->d_sb) ||
1691 +        get_inode_sd_version (dentry->d_inode) == STAT_DATA_V1)
1692 +        return -EOPNOTSUPP;
1693 +    
1694 +    reiserfs_read_lock_xattrs (dentry->d_sb);
1695 +    err = xah->get (dentry->d_inode, name, buffer, size);
1696 +    reiserfs_read_unlock_xattrs (dentry->d_sb);
1697 +    return err;
1698 +}
1699 +
1700 +
1701 +/*
1702 + * Inode operation setxattr()
1703 + *
1704 + * dentry->d_inode->i_sem down
1705 + * BKL held [before 2.5.x]
1706 + */
1707 +int
1708 +reiserfs_setxattr (struct dentry *dentry, const char *name, const void *value,
1709 +                   size_t size, int flags)
1710 +{
1711 +    struct reiserfs_xattr_handler *xah = find_xattr_handler_prefix (name);
1712 +    int err;
1713 +
1714 +    if (!xah || !reiserfs_xattrs(dentry->d_sb) ||
1715 +        get_inode_sd_version (dentry->d_inode) == STAT_DATA_V1)
1716 +        return -EOPNOTSUPP;
1717 +    
1718 +    
1719 +    reiserfs_write_lock_xattrs (dentry->d_sb);
1720 +    err = xah->set (dentry->d_inode, name, value, size, flags);
1721 +    reiserfs_write_unlock_xattrs (dentry->d_sb);
1722 +    return err;
1723 +}
1724 +
1725 +/*
1726 + * Inode operation removexattr()
1727 + *
1728 + * dentry->d_inode->i_sem down
1729 + * BKL held [before 2.5.x]
1730 + */
1731 +int
1732 +reiserfs_removexattr (struct dentry *dentry, const char *name)
1733 +{
1734 +    int err;
1735 +    struct reiserfs_xattr_handler *xah = find_xattr_handler_prefix (name);
1736 +
1737 +    if (!xah || !reiserfs_xattrs(dentry->d_sb) ||
1738 +        get_inode_sd_version (dentry->d_inode) == STAT_DATA_V1)
1739 +        return -EOPNOTSUPP;
1740 +
1741 +    down (&dentry->d_inode->i_zombie);
1742 +    reiserfs_read_lock_xattrs (dentry->d_sb);
1743 +
1744 +    /* Deletion pre-operation */
1745 +    if (xah->del) {
1746 +        err = xah->del (dentry->d_inode, name);
1747 +        if (err) {
1748 +            reiserfs_read_unlock_xattrs (dentry->d_sb);
1749 +            up (&dentry->d_inode->i_zombie);
1750 +            return err;
1751 +        }
1752 +    }
1753 +
1754 +    err = reiserfs_xattr_del (dentry->d_inode, name);
1755 +    reiserfs_read_unlock_xattrs (dentry->d_sb);
1756 +    up (&dentry->d_inode->i_zombie);
1757 +    return err;
1758 +}
1759 +
1760 +
1761 +/* This is what filldir will use:
1762 + * r_pos will always contain the amount of space required for the entire
1763 + * list. If r_pos becomes larger than r_size, we need more space and we
1764 + * return an error indicating this. If r_pos is less than r_size, then we've
1765 + * filled the buffer successfully and we return success */
1766 +struct reiserfs_listxattr_buf {
1767 +    int r_pos;
1768 +    int r_size;
1769 +    char *r_buf;
1770 +    struct inode *r_inode;
1771 +};
1772 +
1773 +static int
1774 +reiserfs_listxattr_filler (void *buf, const char *name, int namelen,
1775 +                           loff_t offset, ino_t ino, unsigned int d_type)
1776 +{
1777 +    struct reiserfs_listxattr_buf *b = (struct reiserfs_listxattr_buf *)buf;
1778 +    int len = 0;
1779 +    if (name[0] != '.' || (namelen != 1 && (name[1] != '.' || namelen != 2))) {
1780 +        struct reiserfs_xattr_handler *xah = find_xattr_handler_prefix (name);
1781 +        if (!xah) return 0; /* Unsupported xattr name, skip it */
1782 +
1783 +        /* We call ->list() twice because the operation isn't required to just
1784 +         * return the name back - we want to make sure we have enough space */
1785 +        len += xah->list (b->r_inode, name, namelen, NULL);
1786 +
1787 +        if (len) {
1788 +            if (b->r_pos + len + 1 <= b->r_size) {
1789 +                char *p = b->r_buf + b->r_pos;
1790 +                p += xah->list (b->r_inode, name, namelen, p);
1791 +                *p++ = '\0';
1792 +            }
1793 +            b->r_pos += len + 1;
1794 +        }
1795 +    }
1796 +
1797 +    return 0;
1798 +}
1799 +/*
1800 + * Inode operation listxattr()
1801 + *
1802 + * dentry->d_inode->i_sem down
1803 + * BKL held [before 2.5.x]
1804 + */
1805 +ssize_t
1806 +reiserfs_listxattr (struct dentry *dentry, char *buffer, size_t size)
1807 +{
1808 +    struct file *fp;
1809 +    struct dentry *dir;
1810 +    int err = 0;
1811 +    struct reiserfs_listxattr_buf buf;
1812 +
1813 +    if (!dentry->d_inode)
1814 +        return -EINVAL;
1815 +
1816 +    if (!reiserfs_xattrs(dentry->d_sb) ||
1817 +        get_inode_sd_version (dentry->d_inode) == STAT_DATA_V1)
1818 +        return -EOPNOTSUPP;
1819 +
1820 +    reiserfs_read_lock_xattrs (dentry->d_sb);
1821 +    dir = open_xa_dir (dentry->d_inode, FL_READONLY);
1822 +    reiserfs_read_unlock_xattrs (dentry->d_sb);
1823 +    if (IS_ERR (dir)) {
1824 +        err = PTR_ERR (dir);
1825 +        if (err == -ENODATA)
1826 +            err = 0; /* Not an error if there aren't any xattrs */
1827 +        goto out;
1828 +    }
1829 +
1830 +    fp = dentry_open (dir, NULL, O_RDWR);
1831 +    if (IS_ERR (fp)) {
1832 +        err = PTR_ERR (fp);
1833 +        /* dentry_open dputs the dentry if it fails */
1834 +        goto out;
1835 +    }
1836 +
1837 +    buf.r_buf = buffer;
1838 +    buf.r_size = buffer ? size : 0;
1839 +    buf.r_pos = 0;
1840 +    buf.r_inode = dentry->d_inode;
1841 +
1842 +    err = xattr_readdir (fp, reiserfs_listxattr_filler, &buf);
1843 +    if (err)
1844 +        goto out_dir;
1845 +
1846 +    if (buf.r_pos > buf.r_size && buffer != NULL)
1847 +        err = -ERANGE;
1848 +    else
1849 +        err = buf.r_pos;
1850 +
1851 +out_dir:
1852 +    fput(fp);
1853 +
1854 +out:
1855 +    return err;
1856 +}
1857 +
1858 +/* This is the implementation for the xattr plugin infrastructure */
1859 +static struct reiserfs_xattr_handler *xattr_handlers;
1860 +static rwlock_t handler_lock = RW_LOCK_UNLOCKED;
1861 +
1862 +static struct reiserfs_xattr_handler *
1863 +find_xattr_handler_prefix (const char *prefix)
1864 +{
1865 +    struct reiserfs_xattr_handler **xah;
1866 +    read_lock (&handler_lock);
1867 +    for (xah = &xattr_handlers; *xah; xah=&(*xah)->next)
1868 +        if (strncmp ((*xah)->prefix, prefix, strlen ((*xah)->prefix)) == 0)
1869 +            break;
1870 +    read_unlock (&handler_lock);
1871 +    return *xah;
1872 +}
1873 +
1874 +int
1875 +reiserfs_xattr_register_handler (struct reiserfs_xattr_handler *handler)
1876 +{
1877 +    int res = 0;
1878 +    struct reiserfs_xattr_handler **xah;
1879 +
1880 +    if (!handler)
1881 +        return -EINVAL;
1882 +
1883 +    if (handler->next)
1884 +        return -EBUSY;
1885 +
1886 +    write_lock (&handler_lock);
1887 +
1888 +    for (xah = &xattr_handlers; *xah; xah=&(*xah)->next) {
1889 +        if (strcmp ((*xah)->prefix, handler->prefix) == 0)
1890 +            break;
1891 +    }
1892 +    if (*xah)
1893 +        res = -EBUSY;
1894 +    else
1895 +        *xah = handler;
1896 +
1897 +    /*
1898 +    if (!res)
1899 +        printk ("ReiserFS: Registered xattr handler for %s\n", handler->prefix);
1900 +    */
1901 +
1902 +    write_unlock (&handler_lock);
1903 +    return res;
1904 +}
1905 +
1906 +int
1907 +reiserfs_xattr_unregister_handler (struct reiserfs_xattr_handler *handler)
1908 +{
1909 +    struct reiserfs_xattr_handler **xah;
1910 +    write_lock (&handler_lock);
1911 +
1912 +    xah = &xattr_handlers;
1913 +    while (*xah) {
1914 +        if (handler == *xah) {
1915 +            *xah = handler->next;
1916 +            handler->next = NULL;
1917 +            write_unlock (&handler_lock);
1918 +            /*
1919 +            printk ("ReiserFS: Unregistered xattr handler for %s\n",
1920 +                    handler->prefix);
1921 +            */
1922 +            return 0;
1923 +        }
1924 +        xah = &(*xah)->next;
1925 +    }
1926 +    write_unlock (&handler_lock);
1927 +    return -EINVAL;
1928 +}
1929 +
1930 +/* We need to take a copy of the mount flags since things like
1931 + * MS_RDONLY don't get set until *after* we're called.
1932 + * mount_flags != mount_options */
1933 +
1934 +int
1935 +reiserfs_xattr_init (struct super_block *s, int mount_flags)
1936 +{
1937 +  int err = 0;
1938 +
1939 +  /* I hate using the _NO_ variant to clear bits. We use the normal variant
1940 +   * everywhere else, so just clear them both here */
1941 +  if (test_bit (REISERFS_NO_XATTRS_USER, &(s->u.reiserfs_sb.s_mount_opt))) {
1942 +    clear_bit (REISERFS_XATTRS_USER, &(s->u.reiserfs_sb.s_mount_opt));
1943 +    clear_bit (REISERFS_NO_XATTRS_USER, &(s->u.reiserfs_sb.s_mount_opt));
1944 +  }
1945 +
1946 +  if (test_bit (REISERFS_NO_POSIXACL, &(s->u.reiserfs_sb.s_mount_opt))) {
1947 +    clear_bit (REISERFS_POSIXACL, &(s->u.reiserfs_sb.s_mount_opt));
1948 +    clear_bit (REISERFS_NO_POSIXACL, &(s->u.reiserfs_sb.s_mount_opt));
1949 +  }
1950 +
1951 +  /* If the user has requested an optional xattrs type (e.g. user/acl), then
1952 +   * enable xattrs. If we're a v3.5 filesystem, this will get caught and
1953 +   * error out. If no optional xattrs are enabled, disable xattrs */
1954 +  if (reiserfs_xattrs_optional (s))
1955 +    set_bit (REISERFS_XATTRS, &(s->u.reiserfs_sb.s_mount_opt));
1956 +  else
1957 +    clear_bit (REISERFS_XATTRS, &(s->u.reiserfs_sb.s_mount_opt));
1958 +
1959 +  if (reiserfs_xattrs (s)) {
1960 +    /* We need generation numbers to ensure that the oid mapping is correct
1961 +     * v3.5 filesystems don't have them. */
1962 +    if (old_format_only (s)) {
1963 +      reiserfs_warning (s, "reiserfs: xattrs/ACLs not supported on pre v3.6 "
1964 +                        "format filesystem. Failing mount.\n");
1965 +      err = -EOPNOTSUPP;
1966 +      goto error;
1967 +    } else if (!s->u.reiserfs_sb.priv_root) {
1968 +      struct dentry *dentry;
1969 +      dentry = lookup_one_len (PRIVROOT_NAME, s->s_root,
1970 +                               strlen (PRIVROOT_NAME));
1971 +      if (!IS_ERR (dentry)) {
1972 +        if (!(mount_flags & MS_RDONLY) && !dentry->d_inode) {
1973 +            struct inode *inode = dentry->d_parent->d_inode;
1974 +            down (&inode->i_sem);
1975 +            err = inode->i_op->mkdir (inode, dentry, 0700);
1976 +            up (&inode->i_sem);
1977 +            if (err) {
1978 +                dput (dentry);
1979 +                dentry = NULL;
1980 +            }
1981 +
1982 +            if (dentry && dentry->d_inode)
1983 +                reiserfs_warning (s, "reiserfs: Created %s on %s - reserved for "
1984 +                                  "xattr storage.\n", PRIVROOT_NAME, 
1985 +                                  bdevname (inode->i_sb->s_dev));
1986 +        }
1987 +      } else
1988 +        err = PTR_ERR (dentry);
1989 +
1990 +      if (!err) {
1991 +          d_drop (dentry);
1992 +          dentry->d_inode->u.reiserfs_i.i_flags |= i_priv_object;
1993 +          s->u.reiserfs_sb.priv_root = dentry;
1994 +      } else { /* xattrs are unavailable */
1995 +          /* If we're read-only it just means that the dir hasn't been
1996 +           * created. Not an error -- just no xattrs on the fs. We'll
1997 +           * check again if we go read-write */
1998 +          if (!(mount_flags & MS_RDONLY)) {
1999 +              reiserfs_warning (s, "reiserfs: xattrs/ACLs enabled and couldn't "
2000 +                             "find/create .reiserfs_priv. Failing mount.\n");
2001 +            err = -EOPNOTSUPP;
2002 +            goto error;
2003 +          }
2004 +          /* Just to speed things up a bit since it won't find anything and
2005 +           * we're read-only */
2006 +          clear_bit (REISERFS_XATTRS, &(s->u.reiserfs_sb.s_mount_opt));
2007 +          clear_bit (REISERFS_XATTRS_USER, &(s->u.reiserfs_sb.s_mount_opt));
2008 +          clear_bit (REISERFS_POSIXACL, &(s->u.reiserfs_sb.s_mount_opt));
2009 +      }
2010 +    }
2011 +  }
2012 +
2013 +error:
2014 +   /* This is only nonzero if there was an error initializing the xattr
2015 +    * directory or if there is a condition where we don't support them. */
2016 +
2017 +    if (err) {
2018 +          clear_bit (REISERFS_XATTRS, &(s->u.reiserfs_sb.s_mount_opt));
2019 +          clear_bit (REISERFS_XATTRS_USER, &(s->u.reiserfs_sb.s_mount_opt));
2020 +          clear_bit (REISERFS_POSIXACL, &(s->u.reiserfs_sb.s_mount_opt));
2021 +    }
2022 +
2023 +    s->s_flags = (s->s_flags & ~MS_POSIXACL) |
2024 +                 (reiserfs_posixacl (s) ? MS_POSIXACL : 0);
2025 +    return err;
2026 +}
2027 diff -urN linux-2.4.22/fs/reiserfs/xattr_acl.c linux-2.4.22-aclea/fs/reiserfs/xattr_acl.c
2028 --- linux-2.4.22/fs/reiserfs/xattr_acl.c        1970-01-01 01:00:00.000000000 +0100
2029 +++ linux-2.4.22-aclea/fs/reiserfs/xattr_acl.c  2003-09-12 17:19:37.000000000 +0200
2030 @@ -0,0 +1,653 @@
2031 +#include <linux/posix_acl.h>
2032 +#include <linux/reiserfs_fs.h>
2033 +#include <linux/errno.h>
2034 +#include <linux/fs.h>
2035 +#include <linux/pagemap.h>
2036 +#include <linux/xattr.h>
2037 +#include <linux/xattr_acl.h>
2038 +#include <linux/reiserfs_xattr.h>
2039 +#include <linux/reiserfs_acl.h>
2040 +#include <asm/uaccess.h>
2041 +
2042 +static int
2043 +xattr_set_acl(struct inode *inode, int type, const void *value, size_t size)
2044 +{
2045 +       struct posix_acl *acl;
2046 +       int error;
2047 +
2048 +       if (!reiserfs_posixacl(inode->i_sb))
2049 +               return -EOPNOTSUPP;
2050 +       if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
2051 +               return -EPERM;
2052 +
2053 +       if (value) {
2054 +               acl = posix_acl_from_xattr(value, size);
2055 +               if (IS_ERR(acl)) {
2056 +                       return PTR_ERR(acl);
2057 +               } else if (acl) {
2058 +                       error = posix_acl_valid(acl);
2059 +                       if (error)
2060 +                               goto release_and_out;
2061 +               }
2062 +       } else
2063 +               acl = NULL;
2064 +
2065 +       error = reiserfs_set_acl (inode, type, acl);
2066 +
2067 +release_and_out:
2068 +       posix_acl_release(acl);
2069 +       return error;
2070 +}
2071 +
2072 +
2073 +static int
2074 +xattr_get_acl(struct inode *inode, int type, void *buffer, size_t size)
2075 +{
2076 +       struct posix_acl *acl;
2077 +       int error;
2078 +
2079 +       if (!reiserfs_posixacl(inode->i_sb))
2080 +               return -EOPNOTSUPP;
2081 +
2082 +       acl = reiserfs_get_acl (inode, type);
2083 +       if (IS_ERR(acl))
2084 +               return PTR_ERR(acl);
2085 +       if (acl == NULL)
2086 +               return -ENODATA;
2087 +       error = posix_acl_to_xattr(acl, buffer, size);
2088 +       posix_acl_release(acl);
2089 +
2090 +       return error;
2091 +}
2092 +
2093 +
2094 +/*
2095 + * Convert from filesystem to in-memory representation.
2096 + */
2097 +static struct posix_acl *
2098 +posix_acl_from_disk(const void *value, size_t size)
2099 +{
2100 +       const char *end = (char *)value + size;
2101 +       int n, count;
2102 +       struct posix_acl *acl;
2103 +
2104 +       if (!value)
2105 +               return NULL;
2106 +       if (size < sizeof(reiserfs_acl_header))
2107 +                return ERR_PTR(-EINVAL);
2108 +       if (((reiserfs_acl_header *)value)->a_version !=
2109 +           cpu_to_le32(REISERFS_ACL_VERSION))
2110 +               return ERR_PTR(-EINVAL);
2111 +       value = (char *)value + sizeof(reiserfs_acl_header);
2112 +       count = reiserfs_acl_count(size);
2113 +       if (count < 0)
2114 +               return ERR_PTR(-EINVAL);
2115 +       if (count == 0)
2116 +               return NULL;
2117 +       acl = posix_acl_alloc(count, GFP_NOFS);
2118 +       if (!acl)
2119 +               return ERR_PTR(-ENOMEM);
2120 +       for (n=0; n < count; n++) {
2121 +               reiserfs_acl_entry *entry =
2122 +                       (reiserfs_acl_entry *)value;
2123 +               if ((char *)value + sizeof(reiserfs_acl_entry_short) > end)
2124 +                       goto fail;
2125 +               acl->a_entries[n].e_tag  = le16_to_cpu(entry->e_tag);
2126 +               acl->a_entries[n].e_perm = le16_to_cpu(entry->e_perm);
2127 +               switch(acl->a_entries[n].e_tag) {
2128 +                       case ACL_USER_OBJ:
2129 +                       case ACL_GROUP_OBJ:
2130 +                       case ACL_MASK:
2131 +                       case ACL_OTHER:
2132 +                               value = (char *)value +
2133 +                                       sizeof(reiserfs_acl_entry_short);
2134 +                               acl->a_entries[n].e_id = ACL_UNDEFINED_ID;
2135 +                               break;
2136 +
2137 +                       case ACL_USER:
2138 +                       case ACL_GROUP:
2139 +                               value = (char *)value + sizeof(reiserfs_acl_entry);
2140 +                               if ((char *)value > end)
2141 +                                       goto fail;
2142 +                               acl->a_entries[n].e_id =
2143 +                                       le32_to_cpu(entry->e_id);
2144 +                               break;
2145 +
2146 +                       default:
2147 +                               goto fail;
2148 +               }
2149 +       }
2150 +       if (value != end)
2151 +               goto fail;
2152 +       return acl;
2153 +
2154 +fail:
2155 +       posix_acl_release(acl);
2156 +       return ERR_PTR(-EINVAL);
2157 +}
2158 +
2159 +/*
2160 + * Convert from in-memory to filesystem representation.
2161 + */
2162 +static void *
2163 +posix_acl_to_disk(const struct posix_acl *acl, size_t *size)
2164 +{
2165 +       reiserfs_acl_header *ext_acl;
2166 +       char *e;
2167 +       int n;
2168 +
2169 +       *size = reiserfs_acl_size(acl->a_count);
2170 +       ext_acl = (reiserfs_acl_header *)kmalloc(sizeof(reiserfs_acl_header) +
2171 +               acl->a_count * sizeof(reiserfs_acl_entry), GFP_NOFS);
2172 +       if (!ext_acl)
2173 +               return ERR_PTR(-ENOMEM);
2174 +       ext_acl->a_version = cpu_to_le32(REISERFS_ACL_VERSION);
2175 +       e = (char *)ext_acl + sizeof(reiserfs_acl_header);
2176 +       for (n=0; n < acl->a_count; n++) {
2177 +               reiserfs_acl_entry *entry = (reiserfs_acl_entry *)e;
2178 +               entry->e_tag  = cpu_to_le16(acl->a_entries[n].e_tag);
2179 +               entry->e_perm = cpu_to_le16(acl->a_entries[n].e_perm);
2180 +               switch(acl->a_entries[n].e_tag) {
2181 +                       case ACL_USER:
2182 +                       case ACL_GROUP:
2183 +                               entry->e_id =
2184 +                                       cpu_to_le32(acl->a_entries[n].e_id);
2185 +                               e += sizeof(reiserfs_acl_entry);
2186 +                               break;
2187 +
2188 +                       case ACL_USER_OBJ:
2189 +                       case ACL_GROUP_OBJ:
2190 +                       case ACL_MASK:
2191 +                       case ACL_OTHER:
2192 +                               e += sizeof(reiserfs_acl_entry_short);
2193 +                               break;
2194 +
2195 +                       default:
2196 +                               goto fail;
2197 +               }
2198 +       }
2199 +       return (char *)ext_acl;
2200 +
2201 +fail:
2202 +       kfree(ext_acl);
2203 +       return ERR_PTR(-EINVAL);
2204 +}
2205 +
2206 +/*
2207 + * Inode operation get_posix_acl().
2208 + *
2209 + * inode->i_sem: down
2210 + * BKL held [before 2.5.x]
2211 + */
2212 +struct posix_acl *
2213 +reiserfs_get_acl(struct inode *inode, int type)
2214 +{
2215 +       char *name, *value;
2216 +       struct posix_acl *acl, **p_acl;
2217 +       size_t size;
2218 +       int retval;
2219 +
2220 +        switch (type) {
2221 +            case ACL_TYPE_ACCESS:
2222 +                name = XATTR_NAME_ACL_ACCESS;
2223 +                p_acl = &inode->u.reiserfs_i.i_acl_access;
2224 +                break;
2225 +            case ACL_TYPE_DEFAULT:
2226 +                name = XATTR_NAME_ACL_DEFAULT;
2227 +                p_acl = &inode->u.reiserfs_i.i_acl_default;
2228 +                break;
2229 +            default:
2230 +                return ERR_PTR (-EINVAL);
2231 +        }
2232 +
2233 +        if (IS_ERR (*p_acl)) {
2234 +            if (PTR_ERR (*p_acl) == -ENODATA)
2235 +                return NULL;
2236 +        } else if (*p_acl != NULL)
2237 +            return posix_acl_dup (*p_acl);
2238 +
2239 +        size = reiserfs_xattr_get (inode, name, NULL, 0);
2240 +        if ((int)size < 0) {
2241 +            if (size == -ENODATA || size == -ENOSYS) {
2242 +               *p_acl = ERR_PTR (-ENODATA);
2243 +               return NULL;
2244 +            }
2245 +            return ERR_PTR (size);
2246 +        }
2247 +
2248 +        value = kmalloc (size, GFP_NOFS);
2249 +        if (!value)
2250 +            return ERR_PTR (-ENOMEM);
2251 +
2252 +       retval = reiserfs_xattr_get(inode, name, value, size);
2253 +       if (retval == -ENODATA || retval == -ENOSYS) {
2254 +               /* This shouldn't actually happen as it should have
2255 +                  been caught above.. but just in case */
2256 +               acl = NULL;
2257 +               *p_acl = ERR_PTR (-ENODATA);
2258 +        } else if (retval < 0) {
2259 +               acl = ERR_PTR(retval);
2260 +       } else {
2261 +               acl = posix_acl_from_disk(value, retval);
2262 +               *p_acl = posix_acl_dup (acl);
2263 +        }
2264 +
2265 +       kfree(value);
2266 +       return acl;
2267 +}
2268 +
2269 +/*
2270 + * Inode operation set_posix_acl().
2271 + *
2272 + * inode->i_sem: down
2273 + * BKL held [before 2.5.x]
2274 + */
2275 +int
2276 +reiserfs_set_acl(struct inode *inode, int type, struct posix_acl *acl)
2277 +{
2278 +        char *name;
2279 +       void *value = NULL;
2280 +       struct posix_acl **p_acl;
2281 +       size_t size;
2282 +       int error;
2283 +
2284 +       if (S_ISLNK(inode->i_mode))
2285 +               return -EOPNOTSUPP;
2286 +
2287 +
2288 +        switch (type) {
2289 +            case ACL_TYPE_ACCESS:
2290 +                name = XATTR_NAME_ACL_ACCESS;
2291 +                p_acl = &inode->u.reiserfs_i.i_acl_access;
2292 +                if (acl) {
2293 +                    mode_t mode = inode->i_mode;
2294 +                    error = posix_acl_equiv_mode (acl, &mode);
2295 +                    if (error < 0)
2296 +                        return error;
2297 +                    else {
2298 +                        inode->i_mode = mode;
2299 +                        if (error == 0)
2300 +                            acl = NULL;
2301 +                    }
2302 +                }
2303 +                break;
2304 +            case ACL_TYPE_DEFAULT:
2305 +                name = XATTR_NAME_ACL_DEFAULT;
2306 +                p_acl = &inode->u.reiserfs_i.i_acl_default;
2307 +                if (!S_ISDIR (inode->i_mode))
2308 +                    return acl ? -EACCES : 0;
2309 +                break;
2310 +            default:
2311 +                return -EINVAL;
2312 +        }
2313 +
2314 +       if (acl) {
2315 +            value = posix_acl_to_disk(acl, &size);
2316 +            if (IS_ERR(value))
2317 +                return (int)PTR_ERR(value);
2318 +            error = reiserfs_xattr_set(inode, name, value, size, 0);
2319 +       } else {
2320 +            error = reiserfs_xattr_del (inode, name);
2321 +            if (error == -ENODATA)
2322 +                error = 0;
2323 +        }
2324 +
2325 +       if (value)
2326 +               kfree(value);
2327 +
2328 +        if (!error) {
2329 +            /* Release the old one */
2330 +            if (!IS_ERR (*p_acl) && *p_acl)
2331 +                posix_acl_release (*p_acl);
2332 +
2333 +            if (acl == NULL)
2334 +                *p_acl = ERR_PTR (-ENODATA);
2335 +            else 
2336 +                *p_acl = posix_acl_dup (acl);
2337 +        }
2338 +
2339 +       return error;
2340 +}
2341 +
2342 +/* dir->i_sem: down,
2343 + * inode is new and not released into the wild yet */
2344 +int
2345 +reiserfs_inherit_default_acl (struct inode *dir, struct dentry *dentry, struct inode *inode)
2346 +{
2347 +    struct posix_acl *acl;
2348 +    int err = 0;
2349 +
2350 +    /* ACLs only get applied to files and directories */
2351 +    if (S_ISLNK (inode->i_mode))
2352 +        return 0;
2353 +
2354 +    /* ACLs can only be used on "new" objects, so if it's an old object
2355 +     * there is nothing to inherit from */
2356 +    if (get_inode_sd_version (dir) == STAT_DATA_V1)
2357 +        goto apply_umask;
2358 +
2359 +    /* Don't apply ACLs to objects in the .reiserfs_priv tree.. This
2360 +     * would be useless since permissions are ignored, and a pain because
2361 +     * it introduces locking cycles */
2362 +    if (is_reiserfs_priv_object (dir)) {
2363 +        inode->u.reiserfs_i.i_flags |= i_priv_object;
2364 +        goto apply_umask;
2365 +    }
2366 +
2367 +    acl = reiserfs_get_acl (dir, ACL_TYPE_DEFAULT);
2368 +    if (IS_ERR (acl)) {
2369 +        if (PTR_ERR (acl) == -ENODATA)
2370 +            goto apply_umask;
2371 +        return PTR_ERR (acl);
2372 +    }
2373 +
2374 +    if (acl) {
2375 +        struct posix_acl *acl_copy;
2376 +        mode_t mode = inode->i_mode;
2377 +        int need_acl;
2378 +
2379 +        /* Copy the default ACL to the default ACL of a new directory */
2380 +        if (S_ISDIR (inode->i_mode)) {
2381 +            err = reiserfs_set_acl (inode, ACL_TYPE_DEFAULT, acl);
2382 +            if (err)
2383 +                goto cleanup;
2384 +        }
2385 +
2386 +        /* Now we reconcile the new ACL and the mode,
2387 +           potentially modifying both */
2388 +        acl_copy = posix_acl_clone (acl, GFP_NOFS);
2389 +        if (!acl_copy) {
2390 +            err = -ENOMEM;
2391 +            goto cleanup;
2392 +        }
2393 +
2394 +
2395 +        need_acl = posix_acl_create_masq (acl_copy, &mode);
2396 +        if (need_acl >= 0) {
2397 +            if (mode != inode->i_mode) {
2398 +                inode->i_mode = mode;
2399 +            }
2400 +
2401 +            /* If we need an ACL.. */
2402 +            if (need_acl > 0) {
2403 +                err = reiserfs_set_acl (inode, ACL_TYPE_ACCESS, acl_copy);
2404 +                if (err) 
2405 +                    goto cleanup_copy;
2406 +            }
2407 +        }
2408 +cleanup_copy:
2409 +        posix_acl_release (acl_copy);
2410 +cleanup:
2411 +        posix_acl_release (acl);
2412 +    } else {
2413 +apply_umask:
2414 +        /* no ACL, apply umask */
2415 +        inode->i_mode &= ~current->fs->umask;
2416 +    }
2417 +
2418 +    return err;
2419 +}
2420 +
2421 +/* Looks up and caches the result of the default ACL.
2422 + * We do this so that we don't need to carry the xattr_sem into
2423 + * reiserfs_new_inode if we don't need to */
2424 +int
2425 +reiserfs_cache_default_acl (struct inode *inode)
2426 +{
2427 +    int ret = 0;
2428 +    if (reiserfs_posixacl (inode->i_sb) &&
2429 +        !is_reiserfs_priv_object (inode)) {
2430 +        struct posix_acl *acl;
2431 +        reiserfs_read_lock_xattrs (inode->i_sb);
2432 +        acl = reiserfs_get_acl (inode, ACL_TYPE_DEFAULT);
2433 +        reiserfs_read_unlock_xattrs (inode->i_sb);
2434 +        ret = acl ? 1 : 0;
2435 +        posix_acl_release (acl);
2436 +    }
2437 +
2438 +    return ret;
2439 +}
2440 +
2441 +static int
2442 +__reiserfs_permission (struct inode *inode, int mask, int need_lock)
2443 +{
2444 +       int mode = inode->i_mode;
2445 +
2446 +       /* Nobody gets write access to a read-only fs */
2447 +       if ((mask & MAY_WRITE) && IS_RDONLY(inode) &&
2448 +           (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
2449 +               return -EROFS;
2450 +
2451 +       /* Nobody gets write access to an immutable file */
2452 +       if ((mask & MAY_WRITE) && IS_IMMUTABLE(inode))
2453 +           return -EACCES;
2454 +
2455 +        /* We don't do permission checks on the internal objects.
2456 +         * Permissions are determined by the "owning" object. */
2457 +        if (is_reiserfs_priv_object (inode))
2458 +            return 0;
2459 +
2460 +       if (current->fsuid == inode->i_uid) {
2461 +               mode >>= 6;
2462 +       } else if (reiserfs_posixacl(inode->i_sb) &&
2463 +                   get_inode_sd_version (inode) != STAT_DATA_V1) {
2464 +                struct posix_acl *acl;
2465 +
2466 +               /* ACL can't contain additional permissions if
2467 +                  the ACL_MASK entry is 0 */
2468 +               if (!(mode & S_IRWXG))
2469 +                       goto check_groups;
2470 +
2471 +                if (need_lock)
2472 +                    reiserfs_read_lock_xattrs (inode->i_sb);
2473 +                acl = reiserfs_get_acl (inode, ACL_TYPE_ACCESS);
2474 +                if (need_lock)
2475 +                    reiserfs_read_unlock_xattrs (inode->i_sb);
2476 +                if (IS_ERR (acl)) {
2477 +                    if (PTR_ERR (acl) == -ENODATA)
2478 +                        goto check_groups;
2479 +                    return PTR_ERR (acl);
2480 +                }
2481 +
2482 +                if (acl) {
2483 +                    int err = posix_acl_permission (inode, acl, mask);
2484 +                    posix_acl_release (acl);
2485 +                    if (err == -EACCES) {
2486 +                        goto check_capabilities;
2487 +                    }
2488 +                    return err;
2489 +               } else {
2490 +                       goto check_groups;
2491 +                }
2492 +
2493 +       } else {
2494 +check_groups:
2495 +               if (in_group_p(inode->i_gid))
2496 +                       mode >>= 3;
2497 +       }
2498 +       if ((mode & mask & S_IRWXO) == mask)
2499 +               return 0;
2500 +
2501 +check_capabilities:
2502 +       /* Allowed to override Discretionary Access Control? */
2503 +        if ((mask & (MAY_READ|MAY_WRITE)) || (inode->i_mode & S_IXUGO))
2504 +                if (capable(CAP_DAC_OVERRIDE))
2505 +                        return 0;
2506 +        /* Read and search granted if capable(CAP_DAC_READ_SEARCH) */
2507 +        if (capable(CAP_DAC_READ_SEARCH) && ((mask == MAY_READ) ||
2508 +            (S_ISDIR(inode->i_mode) && !(mask & MAY_WRITE))))
2509 +                return 0;
2510 +       return -EACCES;
2511 +}
2512 +
2513 +int
2514 +reiserfs_permission (struct inode *inode, int mask)
2515 +{
2516 +    return __reiserfs_permission (inode, mask, 1);
2517 +}
2518 +
2519 +int
2520 +reiserfs_permission_locked (struct inode *inode, int mask)
2521 +{
2522 +    return __reiserfs_permission (inode, mask, 0);
2523 +}
2524 +
2525 +int
2526 +reiserfs_acl_chmod (struct inode *inode)
2527 +{
2528 +        struct posix_acl *acl, *clone;
2529 +        int error;
2530 +
2531 +        if (S_ISLNK(inode->i_mode))
2532 +                return -EOPNOTSUPP;
2533 +
2534 +       if (get_inode_sd_version (inode) == STAT_DATA_V1 ||
2535 +           !reiserfs_posixacl(inode->i_sb))
2536 +        {
2537 +           return 0;
2538 +       }
2539 +
2540 +        reiserfs_read_lock_xattrs (inode->i_sb);
2541 +        acl = reiserfs_get_acl(inode, ACL_TYPE_ACCESS);
2542 +        reiserfs_read_unlock_xattrs (inode->i_sb);
2543 +        if (!acl)
2544 +                return 0;
2545 +        if (IS_ERR(acl))
2546 +                return PTR_ERR(acl);
2547 +        clone = posix_acl_clone(acl, GFP_NOFS);
2548 +        posix_acl_release(acl);
2549 +        if (!clone)
2550 +                return -ENOMEM;
2551 +        error = posix_acl_chmod_masq(clone, inode->i_mode);
2552 +        if (!error) {
2553 +                reiserfs_write_lock_xattrs (inode->i_sb);
2554 +                error = reiserfs_set_acl(inode, ACL_TYPE_ACCESS, clone);
2555 +                reiserfs_write_unlock_xattrs (inode->i_sb);
2556 +        }
2557 +        posix_acl_release(clone);
2558 +        return error;
2559 +}
2560 +
2561 +static int
2562 +posix_acl_access_get(struct inode *inode, const char *name,
2563 +                         void *buffer, size_t size)
2564 +{
2565 +       if (strlen(name) != sizeof(XATTR_NAME_ACL_ACCESS)-1)
2566 +               return -EINVAL;
2567 +       return xattr_get_acl(inode, ACL_TYPE_ACCESS, buffer, size);
2568 +}
2569 +
2570 +static int
2571 +posix_acl_access_set(struct inode *inode, const char *name,
2572 +                         const void *value, size_t size, int flags)
2573 +{
2574 +       if (strlen(name) != sizeof(XATTR_NAME_ACL_ACCESS)-1)
2575 +               return -EINVAL;
2576 +       return xattr_set_acl(inode, ACL_TYPE_ACCESS, value, size);
2577 +}
2578 +
2579 +static int
2580 +posix_acl_access_del (struct inode *inode, const char *name)
2581 +{
2582 +    struct posix_acl **acl = &inode->u.reiserfs_i.i_acl_access;
2583 +    if (strlen(name) != sizeof(XATTR_NAME_ACL_ACCESS)-1)
2584 +       return -EINVAL;
2585 +    if (!IS_ERR (*acl) && *acl) {
2586 +        posix_acl_release (*acl);
2587 +        *acl = ERR_PTR (-ENODATA);
2588 +    }
2589 +
2590 +    return 0;
2591 +}
2592 +
2593 +static int
2594 +posix_acl_access_list (struct inode *inode, const char *name, int namelen, char *out)
2595 +{
2596 +    int len = namelen;
2597 +    if (!reiserfs_posixacl (inode->i_sb))
2598 +        return 0;
2599 +    if (out)
2600 +        memcpy (out, name, len);
2601 +
2602 +    return len;
2603 +}
2604 +
2605 +struct reiserfs_xattr_handler posix_acl_access_handler = {
2606 +    prefix: XATTR_NAME_ACL_ACCESS,
2607 +    get: posix_acl_access_get,
2608 +    set: posix_acl_access_set,
2609 +    del: posix_acl_access_del,
2610 +    list: posix_acl_access_list,
2611 +};
2612 +
2613 +static int
2614 +posix_acl_default_get (struct inode *inode, const char *name,
2615 +                          void *buffer, size_t size)
2616 +{
2617 +       if (strlen(name) != sizeof(XATTR_NAME_ACL_DEFAULT)-1)
2618 +               return -EINVAL;
2619 +       return xattr_get_acl(inode, ACL_TYPE_DEFAULT, buffer, size);
2620 +}
2621 +
2622 +static int
2623 +posix_acl_default_set(struct inode *inode, const char *name,
2624 +                          const void *value, size_t size, int flags)
2625 +{
2626 +       if (strlen(name) != sizeof(XATTR_NAME_ACL_DEFAULT)-1)
2627 +               return -EINVAL;
2628 +       return xattr_set_acl(inode, ACL_TYPE_DEFAULT, value, size);
2629 +}
2630 +
2631 +static int
2632 +posix_acl_default_del (struct inode *inode, const char *name)
2633 +{
2634 +    struct posix_acl **acl = &inode->u.reiserfs_i.i_acl_default;
2635 +    if (strlen(name) != sizeof(XATTR_NAME_ACL_DEFAULT)-1)
2636 +       return -EINVAL;
2637 +    if (!IS_ERR (*acl) && *acl) {
2638 +        posix_acl_release (*acl);
2639 +        *acl = ERR_PTR (-ENODATA);
2640 +    }
2641 +
2642 +    return 0;
2643 +}
2644 +
2645 +static int
2646 +posix_acl_default_list (struct inode *inode, const char *name, int namelen, char *out)
2647 +{
2648 +    int len = namelen;
2649 +    if (!reiserfs_posixacl (inode->i_sb))
2650 +        return 0;
2651 +    if (out)
2652 +        memcpy (out, name, len);
2653 +
2654 +    return len;
2655 +}
2656 +
2657 +struct reiserfs_xattr_handler posix_acl_default_handler = {
2658 +    prefix: XATTR_NAME_ACL_DEFAULT,
2659 +    get: posix_acl_default_get,
2660 +    set: posix_acl_default_set,
2661 +    del: posix_acl_default_del,
2662 +    list: posix_acl_default_list,
2663 +};
2664 +
2665 +int __init
2666 +reiserfs_xattr_posix_acl_init (void)
2667 +{
2668 +    int err;
2669 +    err = reiserfs_xattr_register_handler (&posix_acl_access_handler);
2670 +    if (!err)
2671 +        err = reiserfs_xattr_register_handler (&posix_acl_default_handler);
2672 +    return err;
2673 +}
2674 +
2675 +int
2676 +reiserfs_xattr_posix_acl_exit (void)
2677 +{
2678 +    int err;
2679 +    err = reiserfs_xattr_unregister_handler (&posix_acl_access_handler);
2680 +    if (!err)
2681 +        err = reiserfs_xattr_unregister_handler (&posix_acl_default_handler);
2682 +    return err;
2683 +}
2684 diff -urN linux-2.4.22/fs/reiserfs/xattr_trusted.c linux-2.4.22-aclea/fs/reiserfs/xattr_trusted.c
2685 --- linux-2.4.22/fs/reiserfs/xattr_trusted.c    1970-01-01 01:00:00.000000000 +0100
2686 +++ linux-2.4.22-aclea/fs/reiserfs/xattr_trusted.c      2003-09-12 17:19:43.000000000 +0200
2687 @@ -0,0 +1,97 @@
2688 +#include <linux/reiserfs_fs.h>
2689 +#include <linux/errno.h>
2690 +#include <linux/fs.h>
2691 +#include <linux/pagemap.h>
2692 +#include <linux/xattr.h>
2693 +#include <linux/reiserfs_xattr.h>
2694 +#include <asm/uaccess.h>
2695 +
2696 +#ifdef CONFIG_REISERFS_FS_POSIX_ACL
2697 +# include <linux/reiserfs_acl.h>
2698 +#endif
2699 +
2700 +#define XATTR_TRUSTED_PREFIX "trusted."
2701 +
2702 +static int
2703 +trusted_get (struct inode *inode, const char *name, void *buffer, size_t size)
2704 +{
2705 +    if (strlen(name) < sizeof(XATTR_TRUSTED_PREFIX))
2706 +        return -EINVAL;
2707 +
2708 +    if (!reiserfs_xattrs_trusted (inode->i_sb))
2709 +        return -EOPNOTSUPP;
2710 +
2711 +    if (!(capable(CAP_SYS_ADMIN) || is_reiserfs_priv_object(inode)))
2712 +        return -EPERM;
2713 +
2714 +    return reiserfs_xattr_get (inode, name, buffer, size);
2715 +}
2716 +
2717 +static int
2718 +trusted_set (struct inode *inode, const char *name, const void *buffer,
2719 +          size_t size, int flags)
2720 +{
2721 +    if (strlen(name) < sizeof(XATTR_TRUSTED_PREFIX))
2722 +        return -EINVAL;
2723 +
2724 +    if (!reiserfs_xattrs_trusted (inode->i_sb))
2725 +        return -EOPNOTSUPP;
2726 +
2727 +    if (!(capable(CAP_SYS_ADMIN) || is_reiserfs_priv_object(inode)))
2728 +        return -EPERM;
2729 +
2730 +    return reiserfs_xattr_set (inode, name, buffer, size, flags);
2731 +}
2732 +
2733 +static int
2734 +trusted_del (struct inode *inode, const char *name)
2735 +{
2736 +    if (strlen(name) < sizeof(XATTR_TRUSTED_PREFIX))
2737 +        return -EINVAL;
2738 +
2739 +    if (!reiserfs_xattrs_trusted (inode->i_sb))
2740 +        return -EOPNOTSUPP;
2741 +
2742 +    if (!(capable(CAP_SYS_ADMIN) || is_reiserfs_priv_object(inode)))
2743 +        return -EPERM;
2744 +
2745 +    return 0;
2746 +}
2747 +
2748 +static int
2749 +trusted_list (struct inode *inode, const char *name, int namelen, char *out)
2750 +{
2751 +    int len = namelen;
2752 +
2753 +    if (!reiserfs_xattrs_trusted (inode->i_sb))
2754 +        return 0;
2755 +
2756 +    if (!(capable(CAP_SYS_ADMIN) || is_reiserfs_priv_object(inode)))
2757 +        return 0;
2758 +
2759 +    if (out)
2760 +        memcpy (out, name, len);
2761 +
2762 +    return len;
2763 +}
2764 +
2765 +
2766 +struct reiserfs_xattr_handler trusted_handler = {
2767 +    prefix: XATTR_TRUSTED_PREFIX,
2768 +    get: trusted_get,
2769 +    set: trusted_set,
2770 +    del: trusted_del,
2771 +    list: trusted_list,
2772 +};
2773 +
2774 +int __init
2775 +reiserfs_xattr_trusted_init (void)
2776 +{
2777 +    return reiserfs_xattr_register_handler (&trusted_handler);
2778 +}
2779 +
2780 +int
2781 +reiserfs_xattr_trusted_exit (void)
2782 +{
2783 +    return reiserfs_xattr_unregister_handler (&trusted_handler);
2784 +}
2785 diff -urN linux-2.4.22/fs/reiserfs/xattr_user.c linux-2.4.22-aclea/fs/reiserfs/xattr_user.c
2786 --- linux-2.4.22/fs/reiserfs/xattr_user.c       1970-01-01 01:00:00.000000000 +0100
2787 +++ linux-2.4.22-aclea/fs/reiserfs/xattr_user.c 2003-09-12 17:19:37.000000000 +0200
2788 @@ -0,0 +1,112 @@
2789 +#include <linux/reiserfs_fs.h>
2790 +#include <linux/errno.h>
2791 +#include <linux/fs.h>
2792 +#include <linux/pagemap.h>
2793 +#include <linux/xattr.h>
2794 +#include <linux/reiserfs_xattr.h>
2795 +#include <asm/uaccess.h>
2796 +
2797 +#ifdef CONFIG_REISERFS_FS_POSIX_ACL
2798 +# include <linux/reiserfs_acl.h>
2799 +#endif
2800 +
2801 +#define XATTR_USER_PREFIX "user."
2802 +
2803 +static int
2804 +user_get (struct inode *inode, const char *name, void *buffer, size_t size)
2805 +{
2806 +
2807 +    int error;
2808 +
2809 +    if (strlen(name) < sizeof(XATTR_USER_PREFIX))
2810 +        return -EINVAL;
2811 +
2812 +    if (!reiserfs_xattrs_user (inode->i_sb))
2813 +        return -EOPNOTSUPP;
2814 +
2815 +    error = reiserfs_permission_locked (inode, MAY_READ);
2816 +    if (error)
2817 +        return error;
2818 +
2819 +    return reiserfs_xattr_get (inode, name, buffer, size);
2820 +}
2821 +
2822 +static int
2823 +user_set (struct inode *inode, const char *name, const void *buffer,
2824 +          size_t size, int flags)
2825 +{
2826 +
2827 +    int error;
2828 +
2829 +    if (strlen(name) < sizeof(XATTR_USER_PREFIX))
2830 +        return -EINVAL;
2831 +
2832 +    if (!reiserfs_xattrs_user (inode->i_sb))
2833 +        return -EOPNOTSUPP;
2834 +
2835 +    if (!S_ISREG (inode->i_mode) &&
2836 +        (!S_ISDIR (inode->i_mode) || inode->i_mode & S_ISVTX))
2837 +        return -EPERM;
2838 +
2839 +    error = reiserfs_permission_locked (inode, MAY_WRITE);
2840 +    if (error)
2841 +        return error;
2842 +
2843 +    return reiserfs_xattr_set (inode, name, buffer, size, flags);
2844 +}
2845 +
2846 +static int
2847 +user_del (struct inode *inode, const char *name)
2848 +{
2849 +    int error;
2850 +
2851 +    if (strlen(name) < sizeof(XATTR_USER_PREFIX))
2852 +        return -EINVAL;
2853 +
2854 +    if (!reiserfs_xattrs_user (inode->i_sb))
2855 +        return -EOPNOTSUPP;
2856 +
2857 +    if (!S_ISREG (inode->i_mode) &&
2858 +        (!S_ISDIR (inode->i_mode) || inode->i_mode & S_ISVTX))
2859 +        return -EPERM;
2860 +
2861 +    error = reiserfs_permission_locked (inode, MAY_WRITE);
2862 +    if (error)
2863 +        return error;
2864 +
2865 +    return 0;
2866 +}
2867 +
2868 +static int
2869 +user_list (struct inode *inode, const char *name, int namelen, char *out)
2870 +{
2871 +    int len = namelen;
2872 +    if (!reiserfs_xattrs_user (inode->i_sb))
2873 +        return 0;
2874 +
2875 +    if (out)
2876 +        memcpy (out, name, len);
2877 +
2878 +    return len;
2879 +}
2880 +
2881 +
2882 +struct reiserfs_xattr_handler user_handler = {
2883 +    prefix: XATTR_USER_PREFIX,
2884 +    get: user_get,
2885 +    set: user_set,
2886 +    del: user_del,
2887 +    list: user_list,
2888 +};
2889 +
2890 +int __init
2891 +reiserfs_xattr_user_init (void)
2892 +{
2893 +    return reiserfs_xattr_register_handler (&user_handler);
2894 +}
2895 +
2896 +int
2897 +reiserfs_xattr_user_exit (void)
2898 +{
2899 +    return reiserfs_xattr_unregister_handler (&user_handler);
2900 +}
2901 diff -urN linux-2.4.22/include/linux/reiserfs_acl.h linux-2.4.22-aclea/include/linux/reiserfs_acl.h
2902 --- linux-2.4.22/include/linux/reiserfs_acl.h   1970-01-01 01:00:00.000000000 +0100
2903 +++ linux-2.4.22-aclea/include/linux/reiserfs_acl.h     2003-09-12 17:19:37.000000000 +0200
2904 @@ -0,0 +1,92 @@
2905 +#include <linux/init.h>
2906 +#include <linux/posix_acl.h>
2907 +#include <linux/xattr_acl.h>
2908 +
2909 +#define REISERFS_ACL_VERSION   0x0001
2910 +
2911 +typedef struct {
2912 +       __u16           e_tag;
2913 +       __u16           e_perm;
2914 +       __u32           e_id;
2915 +} reiserfs_acl_entry;
2916 +
2917 +typedef struct {
2918 +       __u16           e_tag;
2919 +       __u16           e_perm;
2920 +} reiserfs_acl_entry_short;
2921 +
2922 +typedef struct {
2923 +       __u32           a_version;
2924 +} reiserfs_acl_header;
2925 +
2926 +static inline size_t reiserfs_acl_size(int count)
2927 +{
2928 +       if (count <= 4) {
2929 +               return sizeof(reiserfs_acl_header) +
2930 +                      count * sizeof(reiserfs_acl_entry_short);
2931 +       } else {
2932 +               return sizeof(reiserfs_acl_header) +
2933 +                      4 * sizeof(reiserfs_acl_entry_short) +
2934 +                      (count - 4) * sizeof(reiserfs_acl_entry);
2935 +       }
2936 +}
2937 +
2938 +static inline int reiserfs_acl_count(size_t size)
2939 +{
2940 +       ssize_t s;
2941 +       size -= sizeof(reiserfs_acl_header);
2942 +       s = size - 4 * sizeof(reiserfs_acl_entry_short);
2943 +       if (s < 0) {
2944 +               if (size % sizeof(reiserfs_acl_entry_short))
2945 +                       return -1;
2946 +               return size / sizeof(reiserfs_acl_entry_short);
2947 +       } else {
2948 +               if (s % sizeof(reiserfs_acl_entry))
2949 +                       return -1;
2950 +               return s / sizeof(reiserfs_acl_entry) + 4;
2951 +       }
2952 +}
2953 +
2954 +
2955 +#ifdef CONFIG_REISERFS_FS_POSIX_ACL
2956 +struct posix_acl * reiserfs_get_acl(struct inode *inode, int type);
2957 +int reiserfs_set_acl(struct inode *inode, int type, struct posix_acl *acl);
2958 +int reiserfs_permission (struct inode *inode, int mask);
2959 +int reiserfs_permission_locked (struct inode *inode, int mask);
2960 +int reiserfs_acl_chmod (struct inode *inode);
2961 +int reiserfs_inherit_default_acl (struct inode *dir, struct dentry *dentry, struct inode *inode);
2962 +int reiserfs_cache_default_acl (struct inode *dir);
2963 +extern int reiserfs_xattr_posix_acl_init (void) __init;
2964 +extern int reiserfs_xattr_posix_acl_exit (void);
2965 +#else
2966 +
2967 +#define reiserfs_permission NULL
2968 +#define reiserfs_set_acl NULL
2969 +#define reiserfs_get_acl NULL
2970 +#define reiserfs_cache_default_acl(inode) 0
2971 +
2972 +static inline int
2973 +reiserfs_xattr_posix_acl_init (void)
2974 +{
2975 +    return 0;
2976 +}
2977 +
2978 +static inline int
2979 +reiserfs_xattr_posix_acl_exit (void)
2980 +{
2981 +    return 0;
2982 +}
2983 +
2984 +static inline int
2985 +reiserfs_acl_chmod (struct inode *inode)
2986 +{
2987 +    return 0;
2988 +}
2989 +
2990 +static inline int
2991 +reiserfs_inherit_default_acl (const struct inode *dir, struct dentry *dentry, struct inode *inode)
2992 +{
2993 +    return 0;
2994 +}
2995 +
2996 +#endif
2997 diff -urN linux-2.4.22/include/linux/reiserfs_fs.h linux-2.4.22-aclea/include/linux/reiserfs_fs.h
2998 --- linux-2.4.22/include/linux/reiserfs_fs.h    2003-08-25 13:44:44.000000000 +0200
2999 +++ linux-2.4.22-aclea/include/linux/reiserfs_fs.h      2003-09-12 17:19:29.000000000 +0200
3000 @@ -1900,6 +1900,7 @@
3001  
3002  void sd_attrs_to_i_attrs( __u16 sd_attrs, struct inode *inode );
3003  void i_attrs_to_sd_attrs( struct inode *inode, __u16 *sd_attrs );
3004 +int reiserfs_setattr(struct dentry *dentry, struct iattr *attr);
3005  
3006  /* namei.c */
3007  inline void set_de_name_and_namelen (struct reiserfs_dir_entry * de);
3008 @@ -1969,6 +1970,7 @@
3009  
3010  /* dir.c */
3011  extern struct inode_operations reiserfs_dir_inode_operations;
3012 +extern struct inode_operations reiserfs_symlink_inode_operations;
3013  extern struct file_operations reiserfs_dir_operations;
3014  
3015  /* tail_conversion.c */
3016 @@ -2189,6 +2191,9 @@
3017  #define REISERFS_IOC_GETVERSION        EXT2_IOC_GETVERSION
3018  #define REISERFS_IOC_SETVERSION         EXT2_IOC_SETVERSION
3019                                  
3020 +/* xattr stuff */
3021 +#define REISERFS_XATTR_DIR_SEM(s) ((s)->u.reiserfs_sb.xattr_dir_sem)
3022 +
3023  #endif /* _LINUX_REISER_FS_H */
3024  
3025  
3026 diff -urN linux-2.4.22/include/linux/reiserfs_fs_i.h linux-2.4.22-aclea/include/linux/reiserfs_fs_i.h
3027 --- linux-2.4.22/include/linux/reiserfs_fs_i.h  2003-06-13 16:51:39.000000000 +0200
3028 +++ linux-2.4.22-aclea/include/linux/reiserfs_fs_i.h    2003-09-12 17:19:37.000000000 +0200
3029 @@ -23,7 +23,8 @@
3030         truncate or unlink. Safe link is used to avoid leakage of disk
3031         space on crash with some files open, but unlinked. */
3032      i_link_saved_unlink_mask   =  0x0010,
3033 -    i_link_saved_truncate_mask =  0x0020
3034 +    i_link_saved_truncate_mask =  0x0020,
3035 +    i_priv_object              =  0x0080,
3036  } reiserfs_inode_flags;
3037  
3038  
3039 @@ -60,6 +61,9 @@
3040       */
3041      unsigned long i_tail_trans_id;
3042      unsigned long i_tail_trans_index;
3043 +
3044 +    struct posix_acl *i_acl_access;
3045 +    struct posix_acl *i_acl_default;
3046  };
3047  
3048  #endif
3049 diff -urN linux-2.4.22/include/linux/reiserfs_fs_sb.h linux-2.4.22-aclea/include/linux/reiserfs_fs_sb.h
3050 --- linux-2.4.22/include/linux/reiserfs_fs_sb.h 2003-08-25 13:44:44.000000000 +0200
3051 +++ linux-2.4.22-aclea/include/linux/reiserfs_fs_sb.h   2003-09-12 17:19:43.000000000 +0200
3052 @@ -6,6 +6,7 @@
3053  
3054  #ifdef __KERNEL__
3055  #include <linux/tqueue.h>
3056 +#include <linux/rwsem.h>
3057  #endif
3058  
3059  //
3060 @@ -171,13 +172,17 @@
3061  ** transaction handle which is passed around for all journal calls
3062  */
3063  struct reiserfs_transaction_handle {
3064 -                               /* ifdef it. -Hans */
3065 -  char *t_caller ;              /* debugging use */
3066 +  struct super_block *t_super ; /* super for this FS when journal_begin was 
3067 +                                  called. saves calls to reiserfs_get_super 
3068 +                                  also used by nested transactions to make
3069 +                                  sure they are nesting on the right FS
3070 +                                  _must_ be first in the handle 
3071 +                               */
3072 +  int t_refcount;
3073    int t_blocks_logged ;         /* number of blocks this writer has logged */
3074    int t_blocks_allocated ;      /* number of blocks this writer allocated */
3075    unsigned long t_trans_id ;    /* sanity check, equals the current trans id */
3076 -  struct super_block *t_super ; /* super for this FS when journal_begin was 
3077 -                                   called. saves calls to reiserfs_get_super */
3078 +  void *t_handle_save ;                /* save existing current->journal_info */
3079    int displace_new_blocks:1;   /* if new block allocation occurres, that block
3080                                    should be displaced from others */
3081  } ;
3082 @@ -413,6 +418,9 @@
3083      reiserfs_proc_info_data_t s_proc_info_data;
3084      struct proc_dir_entry *procdir;
3085      int reserved_blocks; /* amount of blocks reserved for further allocations */
3086 +    struct dentry *priv_root; /* root of /.reiserfs_priv */
3087 +    struct dentry *xattr_root; /* root of /.reiserfs_priv/.xa */
3088 +    struct rw_semaphore xattr_dir_sem;
3089  };
3090  
3091  /* Definitions of reiserfs on-disk properties: */
3092 @@ -459,6 +467,12 @@
3093  #define REISERFS_TEST4 14 
3094  
3095  #define REISERFS_ATTRS (15)
3096 +#define REISERFS_XATTRS 16
3097 +#define REISERFS_XATTRS_USER 17
3098 +#define REISERFS_NO_XATTRS_USER 18
3099 +#define REISERFS_POSIXACL 17
3100 +#define REISERFS_NO_POSIXACL 18
3101 +
3102  
3103  #define reiserfs_r5_hash(s) ((s)->u.reiserfs_sb.s_mount_opt & (1 << FORCE_R5_HASH))
3104  #define reiserfs_rupasov_hash(s) ((s)->u.reiserfs_sb.s_mount_opt & (1 << FORCE_RUPASOV_HASH))
3105 @@ -476,6 +490,17 @@
3106  #define reiserfs_attrs(s) ((s)->u.reiserfs_sb.s_mount_opt & (1 << REISERFS_ATTRS))
3107  #define old_format_only(s) ((s)->u.reiserfs_sb.s_properties & (1 << REISERFS_3_5))
3108  #define convert_reiserfs(s) ((s)->u.reiserfs_sb.s_mount_opt & (1 << REISERFS_CONVERT))
3109 +#define reiserfs_xattrs_user(s) ((s)->u.reiserfs_sb.s_mount_opt & (1 << REISERFS_XATTRS_USER))
3110 +#define reiserfs_xattrs_optional(s) (reiserfs_xattrs_user(s) || reiserfs_posixacl(s))
3111 +#define reiserfs_posixacl(s) ((s)->u.reiserfs_sb.s_mount_opt & (1 << REISERFS_POSIXACL))
3112 +#ifndef CONFIG_REISERFS_FS_XATTR_TRUSTED
3113 +#define reiserfs_xattrs(s) ((s)->u.reiserfs_sb.s_mount_opt & (1 << REISERFS_XATTRS))
3114 +# define reiserfs_xattrs_trusted(s) (0)
3115 +#else
3116 +/* If trusted xattrs are compiled in, they're "always on." */
3117 +# define reiserfs_xattrs(s) (1)
3118 +# define reiserfs_xattrs_trusted(s) (1)
3119 +#endif
3120  
3121  
3122  void reiserfs_file_buffer (struct buffer_head * bh, int list);
3123 diff -urN linux-2.4.22/include/linux/reiserfs_xattr.h linux-2.4.22-aclea/include/linux/reiserfs_xattr.h
3124 --- linux-2.4.22/include/linux/reiserfs_xattr.h 1970-01-01 01:00:00.000000000 +0100
3125 +++ linux-2.4.22-aclea/include/linux/reiserfs_xattr.h   2003-09-12 17:19:43.000000000 +0200
3126 @@ -0,0 +1,132 @@
3127 +/*
3128 +  File: linux/reiserfs_xattr.h
3129 +*/
3130 +
3131 +#include <linux/config.h>
3132 +#include <linux/init.h>
3133 +#include <linux/xattr.h>
3134 +
3135 +/* Magic value in header */
3136 +#define REISERFS_XATTR_MAGIC 0x52465841 /* "RFXA" */
3137 +
3138 +struct reiserfs_xattr_header {
3139 +    __u32 h_magic;              /* magic number for identification */
3140 +    __u32 h_hash;               /* hash of the value */
3141 +};
3142 +
3143 +#ifdef __KERNEL__
3144 +
3145 +struct reiserfs_xattr_handler {
3146 +       char *prefix;
3147 +       int (*get)(struct inode *inode, const char *name, void *buffer,
3148 +                  size_t size);
3149 +       int (*set)(struct inode *inode, const char *name, const void *buffer,
3150 +                  size_t size, int flags);
3151 +       int (*del)(struct inode *inode, const char *name);
3152 +        int (*list)(struct inode *inode, const char *name, int namelen, char *out);
3153 +        struct reiserfs_xattr_handler *next;
3154 +};
3155 +
3156 +
3157 +#ifdef CONFIG_REISERFS_FS_XATTR
3158 +#define is_reiserfs_priv_object(inode) (((inode)->u.reiserfs_i.i_flags & i_priv_object) == i_priv_object)
3159 +ssize_t reiserfs_getxattr (struct dentry *dentry, const char *name,
3160 +                          void *buffer, size_t size);
3161 +int reiserfs_setxattr (struct dentry *dentry, const char *name,
3162 +                       const void *value, size_t size, int flags);
3163 +ssize_t reiserfs_listxattr (struct dentry *dentry, char *buffer, size_t size);
3164 +int reiserfs_removexattr (struct dentry *dentry, const char *name);
3165 +int reiserfs_delete_xattrs (struct inode *inode);
3166 +int reiserfs_chown_xattrs (struct inode *inode, struct iattr *attrs);
3167 +int reiserfs_xattr_init (struct super_block *sb, int mount_flags);
3168 +
3169 +static inline void
3170 +reiserfs_write_lock_xattrs(struct super_block *sb)
3171 +{
3172 +    down_write (&REISERFS_XATTR_DIR_SEM(sb));
3173 +}
3174 +static inline void
3175 +reiserfs_write_unlock_xattrs(struct super_block *sb)
3176 +{
3177 +    up_write (&REISERFS_XATTR_DIR_SEM(sb));
3178 +}
3179 +static inline void
3180 +reiserfs_read_lock_xattrs(struct super_block *sb)
3181 +{
3182 +    down_read (&REISERFS_XATTR_DIR_SEM(sb));
3183 +}
3184 +static inline void
3185 +reiserfs_read_unlock_xattrs(struct super_block *sb)
3186 +{
3187 +    up_read (&REISERFS_XATTR_DIR_SEM(sb));
3188 +}
3189 +#else
3190 +#define is_reiserfs_priv_object(inode) 0
3191 +#define reiserfs_getxattr NULL
3192 +#define reiserfs_setxattr NULL
3193 +#define reiserfs_listxattr NULL
3194 +#define reiserfs_removexattr NULL
3195 +#define reiserfs_write_lock_xattrs(sb)
3196 +#define reiserfs_write_unlock_xattrs(sb)
3197 +#define reiserfs_read_lock_xattrs(sb)
3198 +#define reiserfs_read_unlock_xattrs(sb)
3199 +static inline int
3200 +reiserfs_xattr_init (struct super_block *s, int mount_flags)
3201 +{
3202 +    s->s_flags = (s->s_flags & ~MS_POSIXACL); /* to be sure */
3203 +    return 0;
3204 +}
3205 +
3206 +static inline int
3207 +reiserfs_delete_xattrs (struct inode *inode)
3208 +{
3209 +    return 0;
3210 +}
3211 +
3212 +static inline int
3213 +reiserfs_chown_xattrs (struct inode *inode, struct iattr *attrs)
3214 +{
3215 +    return 0;
3216 +}
3217 +#endif
3218 +
3219 +extern int reiserfs_xattr_register_handler(struct reiserfs_xattr_handler *);
3220 +extern int reiserfs_xattr_unregister_handler(struct reiserfs_xattr_handler *);
3221 +extern int reiserfs_xattr_del (struct inode *, const char *);
3222 +extern int reiserfs_xattr_get (const struct inode *, const char *, void *, size_t);
3223 +extern int reiserfs_xattr_set (struct inode *, const char *, const void *,
3224 +                               size_t, int);
3225 +#ifdef CONFIG_REISERFS_FS_XATTR_USER
3226 +extern int reiserfs_xattr_user_init (void) __init;
3227 +extern int reiserfs_xattr_user_exit (void);
3228 +#else
3229 +static inline int
3230 +reiserfs_xattr_user_init (void)
3231 +{
3232 +    return 0;
3233 +}
3234 +
3235 +static inline int
3236 +reiserfs_xattr_user_exit (void)
3237 +{
3238 +    return 0;
3239 +}
3240 +#endif
3241 +#ifdef CONFIG_REISERFS_FS_XATTR_TRUSTED
3242 +extern int reiserfs_xattr_trusted_init (void) __init;
3243 +extern int reiserfs_xattr_trusted_exit (void);
3244 +#else
3245 +static inline int
3246 +reiserfs_xattr_trusted_init (void)
3247 +{
3248 +    return 0;
3249 +}
3250 +
3251 +static inline int
3252 +reiserfs_xattr_trusted_exit (void)
3253 +{
3254 +    return 0;
3255 +}
3256 +#endif
3257 +
3258 +#endif  /* __KERNEL__ */
This page took 0.373924 seconds and 3 git commands to generate.