]> git.pld-linux.org Git - packages/kernel.git/blob - 01-reiserfs-xattrs-2.4.23+datalogging+quota-03
- IT82XX seriec RAID support
[packages/kernel.git] / 01-reiserfs-xattrs-2.4.23+datalogging+quota-03
1 diff -ruNp -X ../dontdiff linux-2.4.23.datalogging+quota/fs/Config.in linux-2.4.23.xattr/fs/Config.in
2 --- linux-2.4.23.datalogging+quota/fs/Config.in 2003-12-11 12:53:34.170047728 -0500
3 +++ linux-2.4.23.xattr/fs/Config.in     2003-12-11 12:55:03.321494648 -0500
4 @@ -13,6 +13,8 @@ tristate 'Kernel automounter version 4 s
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  
11  dep_tristate 'ADFS file system support (EXPERIMENTAL)' CONFIG_ADFS_FS $CONFIG_EXPERIMENTAL
12  dep_mbool '  ADFS write support (DANGEROUS)' CONFIG_ADFS_FS_RW $CONFIG_ADFS_FS $CONFIG_EXPERIMENTAL
13 diff -ruNp -X ../dontdiff linux-2.4.23.datalogging+quota/fs/reiserfs/Makefile linux-2.4.23.xattr/fs/reiserfs/Makefile
14 --- linux-2.4.23.datalogging+quota/fs/reiserfs/Makefile 2003-12-11 12:54:15.917701120 -0500
15 +++ linux-2.4.23.xattr/fs/reiserfs/Makefile     2003-12-11 12:55:03.322494496 -0500
16 @@ -12,6 +12,9 @@ O_TARGET := reiserfs.o
17  obj-y   := bitmap.o do_balan.o namei.o inode.o file.o dir.o fix_node.o super.o prints.o objectid.o \
18  lbalance.o ibalance.o stree.o hashes.o buffer2.o tail_conversion.o journal.o resize.o item_ops.o ioctl.o procfs.o
19  
20 +obj-$(CONFIG_REISERFS_FS_XATTR) += xattr.o
21 +obj-$(CONFIG_REISERFS_FS_XATTR_USER) += xattr_user.o
22 +
23  obj-m   := $(O_TARGET)
24  
25  # gcc -O2 (the kernel default)  is overaggressive on ppc32 when many inline
26 diff -ruNp -X ../dontdiff linux-2.4.23.datalogging+quota/fs/reiserfs/dir.c linux-2.4.23.xattr/fs/reiserfs/dir.c
27 --- linux-2.4.23.datalogging+quota/fs/reiserfs/dir.c    2003-12-11 12:53:11.351516672 -0500
28 +++ linux-2.4.23.xattr/fs/reiserfs/dir.c        2003-12-11 12:55:03.322494496 -0500
29 @@ -110,6 +110,15 @@ static int reiserfs_readdir (struct file
30                     /* too big to send back to VFS */
31                     continue ;
32                 }
33 +
34 +                /* Ignore the .reiserfs_priv entry */
35 +               if (reiserfs_xattrs (inode->i_sb) && 
36 +                    !old_format_only(inode->i_sb) &&
37 +                    inode->i_sb->u.reiserfs_sb.priv_root &&
38 +                    inode->i_sb->u.reiserfs_sb.priv_root->d_inode &&
39 +                    deh_objectid (deh) == le32_to_cpu (INODE_PKEY(inode->i_sb->u.reiserfs_sb.priv_root->d_inode)->k_objectid))
40 +                  continue;
41 +
42                 d_off = deh_offset (deh);
43                 filp->f_pos = d_off ;
44                 d_ino = deh_objectid (deh);
45 diff -ruNp -X ../dontdiff linux-2.4.23.datalogging+quota/fs/reiserfs/file.c linux-2.4.23.xattr/fs/reiserfs/file.c
46 --- linux-2.4.23.datalogging+quota/fs/reiserfs/file.c   2003-12-11 12:54:29.707604736 -0500
47 +++ linux-2.4.23.xattr/fs/reiserfs/file.c       2003-12-11 12:55:03.323494344 -0500
48 @@ -5,6 +5,7 @@
49  
50  #include <linux/sched.h>
51  #include <linux/reiserfs_fs.h>
52 +#include <linux/reiserfs_xattr.h>
53  #include <linux/smp_lock.h>
54  #include <linux/quotaops.h>
55  
56 @@ -173,6 +174,10 @@ struct file_operations reiserfs_file_ope
57  struct  inode_operations reiserfs_file_inode_operations = {
58      truncate:  reiserfs_vfs_truncate_file,
59      setattr:    reiserfs_setattr,
60 +    setxattr:   reiserfs_setxattr, 
61 +    getxattr:   reiserfs_getxattr, 
62 +    listxattr:   reiserfs_listxattr, 
63 +    removexattr:   reiserfs_removexattr, 
64  };
65  
66  
67 diff -ruNp -X ../dontdiff linux-2.4.23.datalogging+quota/fs/reiserfs/inode.c linux-2.4.23.xattr/fs/reiserfs/inode.c
68 --- linux-2.4.23.datalogging+quota/fs/reiserfs/inode.c  2003-12-11 12:54:29.711604128 -0500
69 +++ linux-2.4.23.xattr/fs/reiserfs/inode.c      2003-12-11 12:58:42.434184456 -0500
70 @@ -6,6 +6,8 @@
71  #include <linux/sched.h>
72  #include <linux/fs.h>
73  #include <linux/reiserfs_fs.h>
74 +#include <linux/reiserfs_xattr.h>
75 +#include <linux/quotaops.h>
76  #include <linux/locks.h>
77  #include <linux/smp_lock.h>
78  #include <linux/quotaops.h>
79 @@ -42,6 +44,8 @@ void reiserfs_delete_inode (struct inode
80      if (INODE_PKEY(inode)->k_objectid != 0) { /* also handles bad_inode case */
81         down (&inode->i_sem); 
82  
83 +       reiserfs_delete_xattrs (inode);
84 +
85         journal_begin(&th, inode->i_sb, jbegin_count) ;
86         reiserfs_update_inode_transaction(inode) ;
87         windex = push_journal_writer("delete_inode") ;
88 @@ -1169,7 +1173,7 @@ static void init_inode (struct inode * i
89         inode->i_op = &reiserfs_dir_inode_operations;
90         inode->i_fop = &reiserfs_dir_operations;
91      } else if (S_ISLNK (inode->i_mode)) {
92 -       inode->i_op = &page_symlink_inode_operations;
93 +       inode->i_op = &reiserfs_symlink_inode_operations;
94         inode->i_mapping->a_ops = &reiserfs_address_space_operations;
95      } else {
96         inode->i_blocks = 0;
97 @@ -2689,6 +2693,70 @@ static int reiserfs_direct_io(int rw, st
98                               reiserfs_get_block_direct_io) ;
99  }
100  
101 +int reiserfs_setattr(struct dentry *dentry, struct iattr *attr)
102 +{
103 +    struct inode *inode = dentry->d_inode ;
104 +    int error ;
105 +    unsigned int ia_valid = attr->ia_valid ;
106 +
107 +    if (ia_valid & ATTR_SIZE) {
108 +       /* version 2 items will be caught by the s_maxbytes check
109 +       ** done for us in vmtruncate
110 +       */
111 +       if (get_inode_item_key_version(inode) == KEY_FORMAT_3_5 &&
112 +           attr->ia_size > MAX_NON_LFS)
113 +            return -EFBIG ;
114 +
115 +        /* During a truncate, we have to make sure the new i_size is in
116 +       ** the transaction before we start dropping updates to data logged
117 +       ** or ordered write data pages.
118 +       */
119 +       if (attr->ia_size < inode->i_size && reiserfs_file_data_log(inode)) {
120 +           struct reiserfs_transaction_handle th ;
121 +           journal_begin(&th, inode->i_sb, 1) ;
122 +           reiserfs_update_sd_size(&th, inode, attr->ia_size) ;
123 +           journal_end(&th, inode->i_sb, 1) ;
124 +       /* fill in hole pointers in the expanding truncate case. */
125 +        } else if (attr->ia_size > inode->i_size) {
126 +           error = generic_cont_expand(inode, attr->ia_size) ;
127 +           if (inode->u.reiserfs_i.i_prealloc_count > 0) {
128 +               struct reiserfs_transaction_handle th ;
129 +               /* we're changing at most 2 bitmaps, inode + super */
130 +               journal_begin(&th, inode->i_sb, 4) ;
131 +               reiserfs_discard_prealloc (&th, inode);
132 +               journal_end(&th, inode->i_sb, 4) ;
133 +           }
134 +           if (error)
135 +               return error ;
136 +       }
137 +    }
138 +
139 +    if ((((attr->ia_valid & ATTR_UID) && (attr->ia_uid & ~0xffff)) ||
140 +        ((attr->ia_valid & ATTR_GID) && (attr->ia_gid & ~0xffff))) &&
141 +       (get_inode_sd_version (inode) == STAT_DATA_V1))
142 +               /* stat data of format v3.5 has 16 bit uid and gid */
143 +           return -EINVAL;
144 +
145 +    error = inode_change_ok(inode, attr) ;
146 +    if (!error) {
147 +       if ((ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) ||
148 +           (ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid)) {
149 +                if (!(attr->ia_valid & ATTR_SIZE))
150 +                    down (&inode->i_sem);
151 +                error = reiserfs_chown_xattrs (inode, attr);
152 +                if (!(attr->ia_valid & ATTR_SIZE))
153 +                    up (&inode->i_sem);
154 +
155 +                if (!error)
156 +                    error = DQUOT_TRANSFER(inode, attr) ? -EDQUOT : 0;
157 +            }
158 +
159 +       if (!error)
160 +           error = inode_setattr(inode, attr) ;
161 +    }
162 +    return error ;
163 +}
164 +
165  struct address_space_operations reiserfs_address_space_operations = {
166      writepage: reiserfs_writepage,
167      readpage: reiserfs_readpage, 
168 diff -ruNp -X ../dontdiff linux-2.4.23.datalogging+quota/fs/reiserfs/namei.c linux-2.4.23.xattr/fs/reiserfs/namei.c
169 --- linux-2.4.23.datalogging+quota/fs/reiserfs/namei.c  2003-12-11 12:54:29.705605040 -0500
170 +++ linux-2.4.23.xattr/fs/reiserfs/namei.c      2003-12-11 12:55:03.327493736 -0500
171 @@ -6,6 +6,7 @@
172  #include <linux/sched.h>
173  #include <linux/bitops.h>
174  #include <linux/reiserfs_fs.h>
175 +#include <linux/reiserfs_xattr.h>
176  #include <linux/smp_lock.h>
177  #include <linux/quotaops.h>
178  
179 @@ -324,10 +325,21 @@ static struct dentry * reiserfs_lookup (
180      retval = reiserfs_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &path_to_entry, &de);
181      pathrelse (&path_to_entry);
182      if (retval == NAME_FOUND) {
183 +        /* Hide the .reiserfs_priv dir */
184 +       if (reiserfs_xattrs (dir->i_sb) &&
185 +            !old_format_only(dir->i_sb) &&
186 +            dir->i_sb->u.reiserfs_sb.priv_root &&
187 +            dir->i_sb->u.reiserfs_sb.priv_root->d_inode &&
188 +            de.de_objectid == le32_to_cpu (INODE_PKEY(dir->i_sb->u.reiserfs_sb.priv_root->d_inode)->k_objectid)) {
189 +            return ERR_PTR (-EACCES);
190 +       }
191         inode = reiserfs_iget (dir->i_sb, (struct cpu_key *)&(de.de_dir_id));
192         if (!inode || IS_ERR(inode)) {
193             return ERR_PTR(-EACCES);
194          }
195 +        /* Propogate the priv_object flag so we know we're in the priv tree */
196 +        if (is_reiserfs_priv_object (dir))
197 +            inode->u.reiserfs_i.i_flags |= i_priv_object;
198      }
199      if ( retval == IO_ERROR ) {
200         return ERR_PTR(-EIO);
201 @@ -908,7 +920,7 @@ static int reiserfs_symlink (struct inod
202      reiserfs_update_inode_transaction(inode) ;
203      reiserfs_update_inode_transaction(parent_dir) ;
204  
205 -    inode->i_op = &page_symlink_inode_operations;
206 +    inode->i_op = &reiserfs_symlink_inode_operations;
207      inode->i_mapping->a_ops = &reiserfs_address_space_operations;
208  
209      // must be sure this inode is written with this transaction
210 @@ -1280,5 +1292,23 @@ struct inode_operations reiserfs_dir_ino
211      rmdir:     reiserfs_rmdir,
212      mknod:     reiserfs_mknod,
213      rename:    reiserfs_rename,
214 +    setattr:   reiserfs_setattr, 
215 +    setxattr:   reiserfs_setxattr, 
216 +    getxattr:   reiserfs_getxattr, 
217 +    listxattr:   reiserfs_listxattr, 
218 +    removexattr:   reiserfs_removexattr, 
219  };
220  
221 +/*
222 + * symlink operations.. same as page_symlink_inode_operations, with xattr
223 + * stuff added
224 + */
225 +struct inode_operations reiserfs_symlink_inode_operations = {
226 +    readlink:       page_readlink,
227 +    follow_link:    page_follow_link,
228 +    setattr:        reiserfs_setattr,
229 +    setxattr:       reiserfs_setxattr,
230 +    getxattr:       reiserfs_getxattr,
231 +    listxattr:      reiserfs_listxattr,
232 +    removexattr:    reiserfs_removexattr,
233 +};
234 diff -ruNp -X ../dontdiff linux-2.4.23.datalogging+quota/fs/reiserfs/super.c linux-2.4.23.xattr/fs/reiserfs/super.c
235 --- linux-2.4.23.datalogging+quota/fs/reiserfs/super.c  2003-12-11 12:54:29.706604888 -0500
236 +++ linux-2.4.23.xattr/fs/reiserfs/super.c      2003-12-11 12:59:19.183597696 -0500
237 @@ -9,6 +9,7 @@
238  #include <linux/vmalloc.h>
239  #include <asm/uaccess.h>
240  #include <linux/reiserfs_fs.h>
241 +#include <linux/reiserfs_xattr.h>
242  #include <linux/smp_lock.h>
243  #include <linux/locks.h>
244  #include <linux/init.h>
245 @@ -354,7 +355,17 @@ static void reiserfs_put_super (struct s
246  {
247    int i;
248    struct reiserfs_transaction_handle th ;
249 +
250 +  if (s->u.reiserfs_sb.xattr_root) {
251 +    d_invalidate (s->u.reiserfs_sb.xattr_root);
252 +    dput (s->u.reiserfs_sb.xattr_root);
253 +  }
254    
255 +  if (s->u.reiserfs_sb.priv_root) {
256 +    d_invalidate (s->u.reiserfs_sb.priv_root);
257 +    dput (s->u.reiserfs_sb.priv_root);
258 +  }
259 +
260    /* change file system state to current state if it was mounted with read-write permissions */
261    if (!(s->s_flags & MS_RDONLY)) {
262      journal_begin(&th, s, 10) ;
263 @@ -639,7 +650,12 @@ static int reiserfs_parse_options (struc
264                 {"noattrs", 0, 0, 0, 1<<REISERFS_ATTRS},
265                 {"usrquota", 0, 0, 0, 0},
266                 {"grpquota", 0, 0, 0, 0},
267 -
268 +#ifdef CONFIG_REISERFS_FS_XATTR
269 +# ifdef CONFIG_REISERFS_FS_XATTR_USER
270 +               {"user_xattr", 0, 0, 1<<REISERFS_XATTRS_USER, 0},
271 +               {"nouser_xattr", 0, 0, 0, 1<<REISERFS_XATTRS_USER},
272 +# endif
273 +#endif
274                 {NULL, 0, 0, 0, 0}
275      };
276         
277 @@ -757,6 +773,7 @@ static int reiserfs_remount (struct supe
278    safe_mask |= 1 << REISERFS_HASHED_RELOCATION;
279    safe_mask |= 1 << REISERFS_TEST4;
280    safe_mask |= 1 << REISERFS_ATTRS;
281 +  safe_mask |= 1 << REISERFS_XATTRS_USER;
282  
283    /* Update the bitmask, taking care to keep
284     * the bits we're not allowed to change here */
285 @@ -771,6 +788,7 @@ static int reiserfs_remount (struct supe
286    }
287  
288    if (*mount_flags & MS_RDONLY) {
289 +    reiserfs_xattr_init (s, *mount_flags);
290      /* remount read-only */
291      if (s->s_flags & MS_RDONLY)
292        /* it is read-only already */
293 @@ -789,6 +807,7 @@ static int reiserfs_remount (struct supe
294    } else {
295      /* remount read-write */
296      if (!(s->s_flags & MS_RDONLY)) {
297 +       reiserfs_xattr_init (s, *mount_flags);
298         handle_data_mode(s, mount_options);
299         return 0; /* We are read-write already */
300      }
301 @@ -811,6 +830,7 @@ static int reiserfs_remount (struct supe
302  
303    if (!( *mount_flags & MS_RDONLY ) ) {
304      finish_unfinished( s );
305 +    reiserfs_xattr_init (s, *mount_flags);
306      handle_data_mode(s, mount_options);
307    }
308    return 0;
309 @@ -1236,6 +1256,8 @@ static struct super_block * reiserfs_rea
310      s->u.reiserfs_sb.s_alloc_options.preallocmin = 4;
311      /* Preallocate by 8 blocks (9-1) at once */
312      s->u.reiserfs_sb.s_alloc_options.preallocsize = 9;
313 +    /* Initialize the rwsem for xattr dir */
314 +    init_rwsem(&s->u.reiserfs_sb.xattr_dir_sem);
315  
316      if (reiserfs_parse_options (s, (char *) data, &(s->u.reiserfs_sb.s_mount_opt), &blocks) == 0) {
317        return NULL;
318 @@ -1378,11 +1400,23 @@ static struct super_block * reiserfs_rea
319                 
320         journal_mark_dirty(&th, s, SB_BUFFER_WITH_SB (s));
321         journal_end(&th, s, 1) ;
322 -       
323 +
324 +       if (reiserfs_xattr_init (s, s->s_flags)) {
325 +           dput (s->s_root);
326 +           s->s_root = NULL;
327 +           goto error;
328 +       }
329 +
330         /* look for files which were to be removed in previous session */
331         finish_unfinished (s);
332  
333         s->s_dirt = 0;
334 +    } else {
335 +       if (reiserfs_xattr_init (s, s->s_flags)) {
336 +           dput (s->s_root);
337 +           s->s_root = NULL;
338 +           goto error;
339 +       }
340      }
341  
342      // mark hash in super block: it could be unset. overwrite should be ok
343 @@ -1447,8 +1481,20 @@ static int __init init_reiserfs_fs (void
344                                        reiserfs_global_version_in_proc );
345         ret = reiserfs_journal_cache_init();
346         if (ret)
347 -           return ret;
348 +           goto failed_journal_cache_init;
349 +
350 +        ret = reiserfs_xattr_user_init ();
351 +        if (ret)
352 +            goto failed_xattr_user_init;
353 +
354          return register_filesystem(&reiserfs_fs_type);
355 +
356 +failed_xattr_user_init:
357 +failed_journal_cache_init:
358 +       reiserfs_proc_unregister_global( "version" );
359 +       reiserfs_proc_info_global_done();
360 +       return ret;
361 +
362  }
363  
364  MODULE_DESCRIPTION("ReiserFS journaled filesystem");
365 @@ -1457,6 +1503,7 @@ MODULE_LICENSE("GPL");
366  
367  static void __exit exit_reiserfs_fs(void)
368  {
369 +       reiserfs_xattr_user_exit ();
370         reiserfs_proc_unregister_global( "version" );
371         reiserfs_proc_info_global_done();
372          unregister_filesystem(&reiserfs_fs_type);
373 diff -ruNp -X ../dontdiff linux-2.4.23.datalogging+quota/fs/reiserfs/xattr.c linux-2.4.23.xattr/fs/reiserfs/xattr.c
374 --- linux-2.4.23.datalogging+quota/fs/reiserfs/xattr.c  1969-12-31 19:00:00.000000000 -0500
375 +++ linux-2.4.23.xattr/fs/reiserfs/xattr.c      2003-12-11 12:55:03.332492976 -0500
376 @@ -0,0 +1,1246 @@
377 +/*
378 + * linux/fs/reiserfs/xattr.c
379 + *
380 + * Copyright (c) 2002 by Jeff Mahoney, <jeffm@suse.com>
381 + *
382 + */
383 +
384 +/*
385 + * In order to implement EAs in a clean, backwards compatible manner,
386 + * they are implemented as files in a "private" directory.
387 + * Each EA is in it's own file, with the directory layout like so (/ is assumed
388 + * to be relative to fs root). Inside the /.reiserfs_priv/xattrs directory,
389 + * directories named using the capital-hex form of the objectid and
390 + * generation number are used. Inside each directory are individual files
391 + * named with the name of the extended attribute.
392 + *
393 + * So, for objectid 12648430, we could have:
394 + * /.reiserfs_priv/xattrs/C0FFEE.0/user.Content-Type
395 + * .. or similar.
396 + *
397 + * The file contents are the text of the EA. The size is known based on the
398 + * stat data describing the file.
399 + *
400 + */
401 +
402 +#include <linux/reiserfs_fs.h>
403 +#include <linux/dcache.h>
404 +#include <linux/errno.h>
405 +#include <linux/fs.h>
406 +#include <linux/file.h>
407 +#include <linux/pagemap.h>
408 +#include <linux/xattr.h>
409 +#include <linux/reiserfs_xattr.h>
410 +#include <linux/mbcache.h>
411 +#include <asm/uaccess.h>
412 +#include <asm/checksum.h>
413 +#include <linux/smp_lock.h>
414 +#include <linux/stat.h>
415 +#include <asm/semaphore.h>
416 +
417 +#define FL_READONLY 128
418 +#define FL_DIR_SEM_HELD 256
419 +#define PRIVROOT_NAME ".reiserfs_priv"
420 +#define XAROOT_NAME   "xattrs"
421 +
422 +static struct reiserfs_xattr_handler *find_xattr_handler_prefix (const char *prefix);
423 +
424 +static struct dentry *
425 +create_xa_root (struct super_block *sb)
426 +{
427 +    struct dentry *privroot = dget (sb->u.reiserfs_sb.priv_root);
428 +    struct dentry *xaroot;
429 +
430 +    /* This needs to be created at mount-time */
431 +    if (!privroot)
432 +        return ERR_PTR(-EOPNOTSUPP);
433 +
434 +    xaroot = lookup_one_len (XAROOT_NAME, privroot, strlen (XAROOT_NAME));
435 +    if (IS_ERR (xaroot)) {
436 +        goto out;
437 +    } else if (!xaroot->d_inode) {
438 +        int err;
439 +        down (&privroot->d_inode->i_sem);
440 +        err = privroot->d_inode->i_op->mkdir (privroot->d_inode, xaroot, 0700);
441 +        up (&privroot->d_inode->i_sem);
442 +
443 +        if (err) {
444 +            dput (xaroot);
445 +            dput (privroot);
446 +            return ERR_PTR (err);
447 +        }
448 +        sb->u.reiserfs_sb.xattr_root = dget (xaroot);
449 +    }
450 +
451 +out:
452 +    dput (privroot);
453 +    return xaroot;
454 +}
455 +
456 +/* This will return a dentry, or error, refering to the xa root directory.
457 + * If the xa root doesn't exist yet, the dentry will be returned without
458 + * an associated inode. This dentry can be used with ->mkdir to create
459 + * the xa directory. */
460 +static struct dentry *
461 +__get_xa_root (struct super_block *s)
462 +{
463 +    struct dentry *privroot = dget (s->u.reiserfs_sb.priv_root);
464 +    struct dentry *xaroot = NULL;
465 +
466 +    if (IS_ERR (privroot) || !privroot)
467 +        return privroot;
468 +
469 +    xaroot = lookup_one_len (XAROOT_NAME, privroot, strlen (XAROOT_NAME));
470 +    if (IS_ERR (xaroot)) {
471 +        goto out;
472 +    } else if (!xaroot->d_inode) {
473 +        dput (xaroot);
474 +        xaroot = NULL;
475 +        goto out;
476 +    }
477 +
478 +    s->u.reiserfs_sb.xattr_root = dget (xaroot);
479 +
480 +out:
481 +    dput (privroot);
482 +    return xaroot;
483 +}
484 +
485 +/* Returns the dentry (or NULL) referring to the root of the extended
486 + * attribute directory tree. If it has already been retreived, it is used.
487 + * Otherwise, we attempt to retreive it from disk. It may also return
488 + * a pointer-encoded error.
489 + */
490 +static inline struct dentry *
491 +get_xa_root (struct super_block *s)
492 +{
493 +    struct dentry *dentry = s->u.reiserfs_sb.xattr_root;
494 +
495 +    if (!dentry)
496 +        dentry = __get_xa_root (s);
497 +    else
498 +        dget (dentry);
499 +    return dentry;
500 +}
501 +
502 +/* Same as above, but only returns a valid dentry or NULL */
503 +struct dentry *
504 +reiserfs_get_xa_root (struct super_block *sb)
505 +{
506 +    struct dentry *dentry;
507 +
508 +    dentry = get_xa_root (sb);
509 +    if (IS_ERR (dentry)) {
510 +        dentry = NULL;
511 +    } else if (dentry && !dentry->d_inode) {
512 +        dput (dentry);
513 +        dentry = NULL;
514 +    }
515 +
516 +    return dentry;
517 +}
518 +
519 +/* Opens the directory corresponding to the inode's extended attribute store.
520 + * If flags allow, the tree to the directory may be created. If creation is
521 + * prohibited, -ENODATA is returned. */
522 +static struct dentry *
523 +open_xa_dir (const struct inode *inode, int flags)
524 +{
525 +    struct dentry *xaroot, *xadir;
526 +    char namebuf[17];
527 +
528 +    xaroot = get_xa_root (inode->i_sb);
529 +    if (IS_ERR (xaroot)) {
530 +        return xaroot;
531 +    } else if (!xaroot) {
532 +        if (flags == 0 || flags & XATTR_CREATE) {
533 +            xaroot = create_xa_root (inode->i_sb);
534 +            if (IS_ERR (xaroot))
535 +                return xaroot;
536 +        }
537 +        if (!xaroot)
538 +            return ERR_PTR (-ENODATA);
539 +    }
540 +
541 +    /* ok, we have xaroot open */
542 +
543 +    snprintf (namebuf, sizeof (namebuf), "%X.%X",
544 +              le32_to_cpu (INODE_PKEY (inode)->k_objectid),
545 +              inode->i_generation);
546 +    xadir = lookup_one_len (namebuf, xaroot, strlen (namebuf));
547 +    if (IS_ERR (xadir)) {
548 +        dput (xaroot);
549 +        return xadir;
550 +    }
551 +    
552 +    if (!xadir->d_inode) {
553 +        int err;
554 +        if (flags == 0 || flags & XATTR_CREATE) {
555 +            /* Although there is nothing else trying to create this directory,
556 +             * another directory with the same hash may be created, so we need
557 +             * to protect against that */
558 +            err = xaroot->d_inode->i_op->mkdir (xaroot->d_inode, xadir, 0700);
559 +            if (err) {
560 +                dput (xaroot);
561 +                dput (xadir);
562 +                return ERR_PTR (err);
563 +            }
564 +        }
565 +        if (!xadir->d_inode) {
566 +            dput (xaroot);
567 +            dput (xadir);
568 +            return ERR_PTR (-ENODATA);
569 +        }
570 +    }
571 +
572 +    dput (xaroot);
573 +    return xadir;
574 +}
575 +
576 +/* Returns a dentry corresponding to a specific extended attribute file
577 + * for the inode. If flags allow, the file is created. Otherwise, a
578 + * valid or negative dentry, or an error is returned. */
579 +static struct dentry *
580 +get_xa_file_dentry (const struct inode *inode, const char *name, int flags)
581 +{
582 +    struct dentry *xadir, *xafile;
583 +    int err = 0;
584 +
585 +    xadir = open_xa_dir (inode, flags);
586 +    if (IS_ERR (xadir)) {
587 +        return ERR_PTR (PTR_ERR (xadir));
588 +    } else if (xadir && !xadir->d_inode) {
589 +        dput (xadir);
590 +        return ERR_PTR (-ENODATA);
591 +    }
592 +
593 +    xafile = lookup_one_len (name, xadir, strlen (name));
594 +    if (IS_ERR (xafile)) {
595 +        dput (xadir);
596 +        return ERR_PTR (PTR_ERR (xafile));
597 +    }
598 +
599 +    if (xafile->d_inode) { /* file exists */
600 +        if (flags & XATTR_CREATE) {
601 +            err = -EEXIST;
602 +            dput (xafile);
603 +            goto out;
604 +        }
605 +    } else if (flags & XATTR_REPLACE || flags & FL_READONLY) {
606 +        goto out;
607 +    } else {
608 +        /* inode->i_sem is down, so nothing else can try to create
609 +         * the same xattr */
610 +        err = xadir->d_inode->i_op->create (xadir->d_inode, xafile,
611 +                                            0700|S_IFREG);
612 +
613 +        if (err) {
614 +            dput (xafile);
615 +            goto out;
616 +        }
617 +    }
618 +
619 +out:
620 +    dput (xadir);
621 +    if (err)
622 +        xafile = ERR_PTR (err);
623 +    return xafile;
624 +}
625 +
626 +
627 +/* Opens a file pointer to the attribute associated with inode */
628 +static struct file *
629 +open_xa_file (const struct inode *inode, const char *name, int flags)
630 +{
631 +    struct dentry *xafile;
632 +    struct file *fp;
633 +
634 +    xafile = get_xa_file_dentry (inode, name, flags);
635 +    if (IS_ERR (xafile))
636 +        return ERR_PTR (PTR_ERR (xafile));
637 +    else if (!xafile->d_inode) {
638 +        dput (xafile);
639 +        return ERR_PTR (-ENODATA);
640 +    }
641 +
642 +    fp = dentry_open (xafile, NULL, O_RDWR);
643 +    /* dentry_open dputs the dentry if it fails */
644 +
645 +    return fp;
646 +}
647 +
648 +
649 +/*
650 + * this is very similar to fs/reiserfs/dir.c:reiserfs_readdir, but
651 + * we need to drop the path before calling the filldir struct.  That
652 + * would be a big performance hit to the non-xattr case, so I've copied
653 + * the whole thing for now. --clm
654 + *
655 + * the big difference is that I go backwards through the directory, 
656 + * and don't mess with f->f_pos, but the idea is the same.  Do some
657 + * action on each and every entry in the directory.
658 + *
659 + * we're called with i_sem held, so there are no worries about the directory
660 + * changing underneath us.
661 + */
662 +static int __xattr_readdir(struct file * filp, void * dirent, filldir_t filldir)
663 +{
664 +    struct inode *inode = filp->f_dentry->d_inode;
665 +    struct cpu_key pos_key;    /* key of current position in the directory (key of directory entry) */
666 +    INITIALIZE_PATH (path_to_entry);
667 +    struct buffer_head * bh;
668 +    int entry_num;
669 +    struct item_head * ih, tmp_ih;
670 +    int search_res;
671 +    char * local_buf;
672 +    loff_t next_pos;
673 +    char small_buf[32] ; /* avoid kmalloc if we can */
674 +    struct reiserfs_de_head *deh;
675 +    int d_reclen;
676 +    char * d_name;
677 +    off_t d_off;
678 +    ino_t d_ino;
679 +    struct reiserfs_dir_entry de;
680 +
681 +
682 +    /* form key for search the next directory entry using f_pos field of
683 +       file structure */
684 +    next_pos = max_reiserfs_offset(inode);
685 +
686 +    while (1) {
687 +research:
688 +       if (next_pos <= DOT_DOT_OFFSET)
689 +           break;
690 +       make_cpu_key (&pos_key, inode, next_pos, TYPE_DIRENTRY, 3);
691 +
692 +       search_res = search_by_entry_key(inode->i_sb, &pos_key, &path_to_entry, &de);
693 +       if (search_res == IO_ERROR) {
694 +           // FIXME: we could just skip part of directory which could
695 +           // not be read
696 +           pathrelse(&path_to_entry);
697 +           return -EIO;
698 +       }
699 +
700 +       if (search_res == NAME_NOT_FOUND)
701 +           de.de_entry_num--;
702 +
703 +       set_de_name_and_namelen(&de);
704 +       entry_num = de.de_entry_num;
705 +       deh = &(de.de_deh[entry_num]);
706 +
707 +       bh = de.de_bh;
708 +       ih = de.de_ih;
709 +
710 +       if (!is_direntry_le_ih(ih)) {
711 +           reiserfs_warning(inode->i_sb, "not direntry %h\n", ih);
712 +           break;
713 +        }
714 +       copy_item_head(&tmp_ih, ih);
715 +               
716 +       /* we must have found item, that is item of this directory, */
717 +       RFALSE( COMP_SHORT_KEYS (&(ih->ih_key), &pos_key),
718 +               "vs-9000: found item %h does not match to dir we readdir %K",
719 +               ih, &pos_key);
720 +
721 +       if (deh_offset(deh) <= DOT_DOT_OFFSET) {
722 +           break;
723 +       }
724 +
725 +       /* look for the previous entry in the directory */
726 +       next_pos = deh_offset (deh) - 1;
727 +
728 +       if (!de_visible (deh))
729 +           /* it is hidden entry */
730 +           continue;
731 +
732 +       d_reclen = entry_length(bh, ih, entry_num);
733 +       d_name = B_I_DEH_ENTRY_FILE_NAME (bh, ih, deh);
734 +       d_off = deh_offset (deh);
735 +       d_ino = deh_objectid (deh);
736 +
737 +       if (!d_name[d_reclen - 1])
738 +           d_reclen = strlen (d_name);
739 +
740 +       if (d_reclen > REISERFS_MAX_NAME(inode->i_sb->s_blocksize)){
741 +           /* too big to send back to VFS */
742 +           continue ;
743 +       }
744 +
745 +        /* Ignore the .reiserfs_priv entry */
746 +        if (reiserfs_xattrs (inode->i_sb) && 
747 +            !old_format_only(inode->i_sb) &&
748 +            deh_objectid (deh) == le32_to_cpu (INODE_PKEY(inode->i_sb->u.reiserfs_sb.priv_root->d_inode)->k_objectid))
749 +          continue;
750 +
751 +       if (d_reclen <= 32) {
752 +         local_buf = small_buf ;
753 +       } else {
754 +           local_buf = reiserfs_kmalloc(d_reclen, GFP_NOFS, inode->i_sb) ;
755 +           if (!local_buf) {
756 +               pathrelse (&path_to_entry);
757 +               return -ENOMEM ;
758 +           }
759 +           if (item_moved (&tmp_ih, &path_to_entry)) {
760 +               reiserfs_kfree(local_buf, d_reclen, inode->i_sb) ;
761 +
762 +               /* sigh, must retry.  Do this same offset again */
763 +               next_pos = d_off;
764 +               goto research;
765 +           }
766 +       }
767 +
768 +       // Note, that we copy name to user space via temporary
769 +       // buffer (local_buf) because filldir will block if
770 +       // user space buffer is swapped out. At that time
771 +       // entry can move to somewhere else
772 +       memcpy (local_buf, d_name, d_reclen);
773 +
774 +       /* the filldir function might need to start transactions,
775 +        * or do who knows what.  Release the path now that we've
776 +        * copied all the important stuff out of the deh
777 +        */
778 +       pathrelse (&path_to_entry);
779 +
780 +       if (filldir (dirent, local_buf, d_reclen, d_off, d_ino, 
781 +                    DT_UNKNOWN) < 0) {
782 +           if (local_buf != small_buf) {
783 +               reiserfs_kfree(local_buf, d_reclen, inode->i_sb) ;
784 +           }
785 +           goto end;
786 +       }
787 +       if (local_buf != small_buf) {
788 +           reiserfs_kfree(local_buf, d_reclen, inode->i_sb) ;
789 +       }
790 +    } /* while */
791 +
792 +end:
793 +    pathrelse (&path_to_entry);
794 +    return 0;
795 +}
796 +
797 +/* 
798 + * this could be done with dedicated readdir ops for the xattr files,
799 + * but I want to get something working asap
800 + * this is stolen from vfs_readdir
801 + *
802 + */
803 +static
804 +int xattr_readdir(struct file *file, filldir_t filler, void *buf)
805 +{
806 +        struct inode *inode = file->f_dentry->d_inode;
807 +        int res = -ENOTDIR;
808 +        if (!file->f_op || !file->f_op->readdir)
809 +                goto out;
810 +        down(&inode->i_sem);
811 +        down(&inode->i_zombie);
812 +        res = -ENOENT;
813 +        if (!IS_DEADDIR(inode)) {
814 +                lock_kernel();
815 +                res = __xattr_readdir(file, buf, filler);
816 +                unlock_kernel();
817 +        }
818 +        up(&inode->i_zombie);
819 +        up(&inode->i_sem);
820 +out:
821 +        return res;
822 +}
823 +
824 +
825 +/* Internal operations on file data */
826 +static inline void
827 +reiserfs_put_page(struct page *page)
828 +{
829 +        kunmap(page);
830 +        page_cache_release(page);
831 +}
832 +
833 +static struct page *
834 +reiserfs_get_page(struct inode *dir, unsigned long n)
835 +{
836 +        struct address_space *mapping = dir->i_mapping; 
837 +        struct page *page;
838 +        /* We can deadlock if we try to free dentries,
839 +           and an unlink/rmdir has just occured - GFP_NOFS avoids this */
840 +        mapping->gfp_mask = GFP_NOFS;
841 +        page = read_cache_page (mapping, n,
842 +                                (filler_t*)mapping->a_ops->readpage, NULL);
843 +        if (!IS_ERR(page)) {
844 +                wait_on_page(page);
845 +                kmap(page);
846 +                if (!Page_Uptodate(page))
847 +                        goto fail;
848 +
849 +                if (PageError(page))
850 +                        goto fail;
851 +        }
852 +        return page;
853 +
854 +fail:
855 +        reiserfs_put_page(page);
856 +        return ERR_PTR(-EIO);
857 +}
858 +
859 +static inline __u32
860 +xattr_hash (const char *msg, int len)
861 +{
862 +    return csum_partial (msg, len, 0);
863 +}
864 +
865 +/* Generic extended attribute operations that can be used by xa plugins */
866 +
867 +/*
868 + * inode->i_sem: down
869 + */
870 +int
871 +reiserfs_xattr_set (struct inode *inode, const char *name, const void *buffer,
872 +                    size_t buffer_size, int flags)
873 +{
874 +    int err = 0;
875 +    struct file *fp;
876 +    struct page *page;
877 +    char *data;
878 +    struct address_space *mapping;
879 +    size_t file_pos = 0;
880 +    size_t buffer_pos = 0;
881 +    struct inode *xinode;
882 +    struct iattr newattrs;
883 +    __u32 xahash = 0;
884 +
885 +    if (get_inode_sd_version (inode) == STAT_DATA_V1)
886 +        return -EOPNOTSUPP;
887 +
888 +    /* Empty xattrs are ok, they're just empty files, no hash */
889 +    if (buffer && buffer_size)
890 +        xahash = xattr_hash (buffer, buffer_size);
891 +
892 +open_file:
893 +    fp = open_xa_file (inode, name, flags);
894 +    if (IS_ERR (fp)) {
895 +        err = PTR_ERR (fp);
896 +        goto out;
897 +    }
898 +
899 +    xinode = fp->f_dentry->d_inode;
900 +
901 +    /* we need to copy it off.. */
902 +    if (xinode->i_nlink > 1) {
903 +       fput(fp);
904 +        err = reiserfs_xattr_del (inode, name);
905 +        if (err < 0)
906 +            goto out;
907 +        /* We just killed the old one, we're not replacing anymore */
908 +        if (flags & XATTR_REPLACE)
909 +            flags &= ~XATTR_REPLACE;
910 +        goto open_file;
911 +    }
912 +
913 +    /* Resize it so we're ok to write there */
914 +    newattrs.ia_size = buffer_size;
915 +    newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
916 +    down (&xinode->i_sem);
917 +    err = notify_change(fp->f_dentry, &newattrs);
918 +    if (err)
919 +        goto out_filp;
920 +
921 +    mapping = xinode->i_mapping;
922 +    while (buffer_pos < buffer_size || buffer_pos == 0) {
923 +        size_t chunk;
924 +        size_t skip = 0;
925 +        size_t page_offset = (file_pos & (PAGE_CACHE_SIZE - 1));
926 +        if (buffer_size - buffer_pos > PAGE_CACHE_SIZE)
927 +            chunk = PAGE_CACHE_SIZE;
928 +        else
929 +            chunk = buffer_size - buffer_pos;
930 +
931 +        page = reiserfs_get_page (xinode, file_pos >> PAGE_CACHE_SHIFT);
932 +        if (IS_ERR (page)) {
933 +            err = PTR_ERR (page);
934 +            goto out_filp;
935 +        }
936 +
937 +        lock_page (page);
938 +        data = page_address (page);
939 +
940 +        if (file_pos == 0) {
941 +            struct reiserfs_xattr_header *rxh;
942 +            skip = file_pos = sizeof (struct reiserfs_xattr_header);
943 +            if (chunk + skip > PAGE_CACHE_SIZE)
944 +                chunk = PAGE_CACHE_SIZE - skip;
945 +            rxh = (struct reiserfs_xattr_header *)data;
946 +            rxh->h_magic = cpu_to_le32 (REISERFS_XATTR_MAGIC);
947 +            rxh->h_hash = cpu_to_le32 (xahash);
948 +        }
949 +
950 +        err = mapping->a_ops->prepare_write (fp, page, page_offset,
951 +                                             page_offset + chunk + skip);
952 +        if (!err) {
953 +           if (buffer)
954 +               memcpy (data + skip, buffer + buffer_pos, chunk);
955 +            err = mapping->a_ops->commit_write (fp, page, page_offset,
956 +                                                page_offset + chunk + skip);
957 +       }
958 +        UnlockPage (page);
959 +        reiserfs_put_page (page);
960 +        buffer_pos += chunk;
961 +        file_pos += chunk;
962 +        skip = 0;
963 +        if (err || buffer_size == 0 || !buffer)
964 +            break;
965 +    }
966 +
967 +out_filp:
968 +    up (&xinode->i_sem);
969 +    fput(fp);
970 +
971 +out:
972 +    return err;
973 +}
974 +
975 +/*
976 + * inode->i_sem: down
977 + */
978 +int
979 +reiserfs_xattr_get (const struct inode *inode, const char *name, void *buffer,
980 +                    size_t buffer_size)
981 +{
982 +    ssize_t err = 0;
983 +    struct file *fp;
984 +    size_t isize;
985 +    size_t file_pos = 0;
986 +    size_t buffer_pos = 0;
987 +    struct page *page;
988 +    struct inode *xinode;
989 +    __u32 hash = 0;
990 +
991 +    /* We can't have xattrs attached to v1 items since they don't have
992 +     * generation numbers */
993 +    if (get_inode_sd_version (inode) == STAT_DATA_V1)
994 +        return -EOPNOTSUPP;
995 +
996 +    fp = open_xa_file (inode, name, FL_READONLY);
997 +    if (IS_ERR (fp)) {
998 +        err = PTR_ERR (fp);
999 +        goto out;
1000 +    }
1001 +
1002 +    xinode = fp->f_dentry->d_inode;
1003 +    isize = xinode->i_size;
1004 +
1005 +    /* Just return the size needed */
1006 +    if (buffer == NULL) {
1007 +        err = isize - sizeof (struct reiserfs_xattr_header);
1008 +        goto out_dput;
1009 +    }
1010 +
1011 +    if (buffer_size < isize - sizeof (struct reiserfs_xattr_header)) {
1012 +        err = -ERANGE;
1013 +        goto out_dput;
1014 +    }
1015 +    
1016 +    while (file_pos < isize) {
1017 +        size_t chunk;
1018 +        char *data;
1019 +        size_t skip = 0;
1020 +        if (isize - file_pos > PAGE_CACHE_SIZE)
1021 +            chunk = PAGE_CACHE_SIZE;
1022 +        else
1023 +            chunk = isize - file_pos;
1024 +
1025 +        page = reiserfs_get_page (xinode, file_pos >> PAGE_CACHE_SHIFT);
1026 +        if (IS_ERR (page)) {
1027 +            err = PTR_ERR (page);
1028 +            goto out_dput;
1029 +        }
1030 +
1031 +        lock_page (page);
1032 +        data = page_address (page);
1033 +        if (file_pos == 0) {
1034 +            struct reiserfs_xattr_header *rxh =
1035 +                                        (struct reiserfs_xattr_header *)data;
1036 +            skip = file_pos = sizeof (struct reiserfs_xattr_header);
1037 +            chunk -= skip;
1038 +            /* Magic doesn't match up.. */
1039 +            if (rxh->h_magic != cpu_to_le32 (REISERFS_XATTR_MAGIC)) {
1040 +                UnlockPage (page);
1041 +                reiserfs_put_page (page);
1042 +                err = -EIO;
1043 +                goto out_dput;
1044 +            }
1045 +            hash = le32_to_cpu (rxh->h_hash);
1046 +        }
1047 +        memcpy (buffer + buffer_pos, data + skip, chunk);
1048 +        UnlockPage (page);
1049 +        reiserfs_put_page (page);
1050 +        file_pos += chunk;
1051 +        buffer_pos += chunk;
1052 +        skip = 0;
1053 +    }
1054 +    err = isize - sizeof (struct reiserfs_xattr_header);
1055 +
1056 +    if (xattr_hash (buffer, isize - sizeof (struct reiserfs_xattr_header)) != hash)
1057 +        err = -EIO;
1058 +
1059 +out_dput:
1060 +    fput(fp);
1061 +
1062 +out:
1063 +    return err;
1064 +}
1065 +
1066 +static int
1067 +__reiserfs_xattr_del (struct dentry *xadir, const char *name, int namelen)
1068 +{
1069 +    struct dentry *file;
1070 +    struct inode *dir = xadir->d_inode;
1071 +    int err = 0;
1072 +
1073 +    file = lookup_one_len (name, xadir, namelen);
1074 +    if (IS_ERR (file)) {
1075 +        err = PTR_ERR (file);
1076 +        goto out;
1077 +    } else if (!file->d_inode) {
1078 +        err = -ENODATA;
1079 +        goto out_file;
1080 +    }
1081 +
1082 +    /* Skip directories.. */
1083 +    if (S_ISDIR (file->d_inode->i_mode))
1084 +        goto out_file;
1085 +
1086 +    if (!is_reiserfs_priv_object (file->d_inode)) {
1087 +        reiserfs_warning (dir->i_sb, "trying to delete objectid %08x, which isn't an xattr!\n", le32_to_cpu (INODE_PKEY (file->d_inode)->k_objectid));
1088 +        dput (file);
1089 +        return -EIO;
1090 +    }
1091 +
1092 +    err = dir->i_op->unlink (dir, file);
1093 +    if (!err)
1094 +        d_delete (file);
1095 +
1096 +out_file:
1097 +    dput (file);
1098 +
1099 +out:
1100 +    return err;
1101 +}
1102 +
1103 +
1104 +int
1105 +reiserfs_xattr_del (struct inode *inode, const char *name)
1106 +{
1107 +    struct dentry *dir;
1108 +    int err;
1109 +
1110 +    dir = open_xa_dir (inode, FL_READONLY);
1111 +    if (IS_ERR (dir)) {
1112 +        err = PTR_ERR (dir);
1113 +        goto out;
1114 +    }
1115 +
1116 +    err = __reiserfs_xattr_del (dir, name, strlen (name));
1117 +    dput (dir);
1118 +
1119 +out:
1120 +    return err;
1121 +}
1122 +
1123 +/* The following are side effects of other operations that aren't explicitly
1124 + * modifying extended attributes. This includes operations such as permissions
1125 + * or ownership changes, object deletions, etc. */
1126
1127 +static int
1128 +reiserfs_delete_xattrs_filler (void *buf, const char *name, int namelen,
1129 +                               loff_t offset, ino_t ino, unsigned int d_type)
1130 +{
1131 +    struct dentry *xadir = (struct dentry *)buf;
1132 +
1133 +    return __reiserfs_xattr_del (xadir, name, namelen);
1134 +
1135 +}
1136 +
1137 +int
1138 +reiserfs_delete_xattrs (struct inode *inode)
1139 +{
1140 +    struct file *fp;
1141 +    struct dentry *dir, *root;
1142 +    int err = 0;
1143 +
1144 +    /* Skip out, an xattr has no xattrs associated with it */
1145 +    if (is_reiserfs_priv_object (inode) ||
1146 +        get_inode_sd_version (inode) == STAT_DATA_V1 || 
1147 +        !reiserfs_xattrs(inode->i_sb))
1148 +    {
1149 +        return 0;
1150 +    }
1151 +    reiserfs_read_lock_xattrs (inode->i_sb);
1152 +    dir = open_xa_dir (inode, FL_READONLY);
1153 +    reiserfs_read_unlock_xattrs (inode->i_sb);
1154 +    if (IS_ERR (dir)) {
1155 +        err = PTR_ERR (dir);
1156 +        goto out;
1157 +    } else if (!dir->d_inode) {
1158 +        dput (dir);
1159 +        return 0;
1160 +    }
1161 +
1162 +    fp = dentry_open (dir, NULL, O_RDWR);
1163 +    if (IS_ERR (fp)) {
1164 +        err = PTR_ERR (fp);
1165 +        /* dentry_open dputs the dentry if it fails */
1166 +        goto out;
1167 +    }
1168 +
1169 +    lock_kernel ();
1170 +    err = xattr_readdir (fp, reiserfs_delete_xattrs_filler, dir);
1171 +    if (err) {
1172 +        unlock_kernel ();
1173 +        goto out_dir;
1174 +    }
1175 +
1176 +    /* Leftovers besides . and .. -- that's not good. */
1177 +    if (dir->d_inode->i_nlink <= 2) {
1178 +        root = get_xa_root (inode->i_sb);
1179 +        reiserfs_write_lock_xattrs (inode->i_sb);
1180 +        err = vfs_rmdir (root->d_inode, dir);
1181 +        reiserfs_write_unlock_xattrs (inode->i_sb);
1182 +        dput (root);
1183 +    } else {
1184 +        reiserfs_warning (inode->i_sb, "Couldn't remove all entries in directory\n");
1185 +    }
1186 +    unlock_kernel ();
1187 +
1188 +out_dir:
1189 +    fput(fp);
1190 +
1191 +out:
1192 +    return err;
1193 +}
1194 +
1195 +struct reiserfs_chown_buf {
1196 +    struct inode *inode;
1197 +    struct dentry *xadir;
1198 +    struct iattr *attrs;
1199 +};
1200 +
1201 +/* XXX: If there is a better way to do this, I'd love to hear about it */
1202 +static int
1203 +reiserfs_chown_xattrs_filler (void *buf, const char *name, int namelen,
1204 +                               loff_t offset, ino_t ino, unsigned int d_type)
1205 +{
1206 +    struct reiserfs_chown_buf *chown_buf = (struct reiserfs_chown_buf *)buf;
1207 +    struct dentry *xafile, *xadir = chown_buf->xadir;
1208 +    struct iattr *attrs = chown_buf->attrs;
1209 +    int err = 0;
1210 +
1211 +    xafile = lookup_one_len (name, xadir, namelen);
1212 +    if (IS_ERR (xafile))
1213 +        return PTR_ERR (xafile);
1214 +    else if (!xafile->d_inode) {
1215 +        dput (xafile);
1216 +        return -ENODATA;
1217 +    }
1218 +
1219 +    if (!S_ISDIR (xafile->d_inode->i_mode))
1220 +        err = notify_change (xafile, attrs);
1221 +    dput (xafile);
1222 +
1223 +    return err;
1224 +}
1225 +
1226 +int
1227 +reiserfs_chown_xattrs (struct inode *inode, struct iattr *attrs)
1228 +{
1229 +    struct file *fp;
1230 +    struct dentry *dir;
1231 +    int err = 0;
1232 +    struct reiserfs_chown_buf buf;
1233 +    unsigned int ia_valid = attrs->ia_valid;
1234 +
1235 +    /* Skip out, an xattr has no xattrs associated with it */
1236 +    if (is_reiserfs_priv_object (inode) ||
1237 +        get_inode_sd_version (inode) == STAT_DATA_V1 || 
1238 +        !reiserfs_xattrs(inode->i_sb))
1239 +    {
1240 +        return 0;
1241 +    }
1242 +    reiserfs_read_lock_xattrs (inode->i_sb);
1243 +    dir = open_xa_dir (inode, FL_READONLY);
1244 +    reiserfs_read_unlock_xattrs (inode->i_sb);
1245 +    if (IS_ERR (dir)) {
1246 +        if (PTR_ERR (dir) != -ENODATA)
1247 +            err = PTR_ERR (dir);
1248 +        goto out;
1249 +    } else if (!dir->d_inode) {
1250 +        dput (dir);
1251 +        goto out;
1252 +    }
1253 +
1254 +    fp = dentry_open (dir, NULL, O_RDWR);
1255 +    if (IS_ERR (fp)) {
1256 +        err = PTR_ERR (fp);
1257 +        /* dentry_open dputs the dentry if it fails */
1258 +        goto out;
1259 +    }
1260 +
1261 +    lock_kernel ();
1262 +
1263 +    attrs->ia_valid &= (ATTR_UID | ATTR_GID | ATTR_CTIME);
1264 +    buf.xadir = dir;
1265 +    buf.attrs = attrs;
1266 +    buf.inode = inode;
1267 +
1268 +    err = xattr_readdir (fp, reiserfs_chown_xattrs_filler, &buf);
1269 +    if (err) {
1270 +        unlock_kernel ();
1271 +        goto out_dir;
1272 +    }
1273 +
1274 +    err = notify_change (dir, attrs);
1275 +    unlock_kernel ();
1276 +
1277 +out_dir:
1278 +    fput(fp);
1279 +
1280 +out:
1281 +    attrs->ia_valid = ia_valid;
1282 +    return err;
1283 +}
1284 +
1285 +
1286 +/* Actual operations that are exported to VFS-land */
1287 +
1288 +/*
1289 + * Inode operation getxattr()
1290 + * dentry->d_inode->i_sem down
1291 + * BKL held [before 2.5.x]
1292 + */
1293 +ssize_t
1294 +reiserfs_getxattr (struct dentry *dentry, const char *name, void *buffer,
1295 +                   size_t size)
1296 +{
1297 +    struct reiserfs_xattr_handler *xah = find_xattr_handler_prefix (name);
1298 +    int err;
1299 +
1300 +    if (!xah || !reiserfs_xattrs(dentry->d_sb) ||
1301 +        get_inode_sd_version (dentry->d_inode) == STAT_DATA_V1)
1302 +        return -EOPNOTSUPP;
1303 +    
1304 +    reiserfs_read_lock_xattrs (dentry->d_sb);
1305 +    err = xah->get (dentry->d_inode, name, buffer, size);
1306 +    reiserfs_read_unlock_xattrs (dentry->d_sb);
1307 +    return err;
1308 +}
1309 +
1310 +
1311 +/*
1312 + * Inode operation setxattr()
1313 + *
1314 + * dentry->d_inode->i_sem down
1315 + * BKL held [before 2.5.x]
1316 + */
1317 +int
1318 +reiserfs_setxattr (struct dentry *dentry, const char *name, const void *value,
1319 +                   size_t size, int flags)
1320 +{
1321 +    struct reiserfs_xattr_handler *xah = find_xattr_handler_prefix (name);
1322 +    int err;
1323 +
1324 +    if (!xah || !reiserfs_xattrs(dentry->d_sb) ||
1325 +        get_inode_sd_version (dentry->d_inode) == STAT_DATA_V1)
1326 +        return -EOPNOTSUPP;
1327 +    
1328 +    
1329 +    reiserfs_write_lock_xattrs (dentry->d_sb);
1330 +    err = xah->set (dentry->d_inode, name, value, size, flags);
1331 +    reiserfs_write_unlock_xattrs (dentry->d_sb);
1332 +    return err;
1333 +}
1334 +
1335 +/*
1336 + * Inode operation removexattr()
1337 + *
1338 + * dentry->d_inode->i_sem down
1339 + * BKL held [before 2.5.x]
1340 + */
1341 +int
1342 +reiserfs_removexattr (struct dentry *dentry, const char *name)
1343 +{
1344 +    int err;
1345 +    struct reiserfs_xattr_handler *xah = find_xattr_handler_prefix (name);
1346 +
1347 +    if (!xah || !reiserfs_xattrs(dentry->d_sb) ||
1348 +        get_inode_sd_version (dentry->d_inode) == STAT_DATA_V1)
1349 +        return -EOPNOTSUPP;
1350 +
1351 +    down (&dentry->d_inode->i_zombie);
1352 +    reiserfs_read_lock_xattrs (dentry->d_sb);
1353 +
1354 +    /* Deletion pre-operation */
1355 +    if (xah->del) {
1356 +        err = xah->del (dentry->d_inode, name);
1357 +        if (err) {
1358 +            reiserfs_read_unlock_xattrs (dentry->d_sb);
1359 +            up (&dentry->d_inode->i_zombie);
1360 +            return err;
1361 +        }
1362 +    }
1363 +
1364 +    err = reiserfs_xattr_del (dentry->d_inode, name);
1365 +    reiserfs_read_unlock_xattrs (dentry->d_sb);
1366 +    up (&dentry->d_inode->i_zombie);
1367 +    return err;
1368 +}
1369 +
1370 +
1371 +/* This is what filldir will use:
1372 + * r_pos will always contain the amount of space required for the entire
1373 + * list. If r_pos becomes larger than r_size, we need more space and we
1374 + * return an error indicating this. If r_pos is less than r_size, then we've
1375 + * filled the buffer successfully and we return success */
1376 +struct reiserfs_listxattr_buf {
1377 +    int r_pos;
1378 +    int r_size;
1379 +    char *r_buf;
1380 +    struct inode *r_inode;
1381 +};
1382 +
1383 +static int
1384 +reiserfs_listxattr_filler (void *buf, const char *name, int namelen,
1385 +                           loff_t offset, ino_t ino, unsigned int d_type)
1386 +{
1387 +    struct reiserfs_listxattr_buf *b = (struct reiserfs_listxattr_buf *)buf;
1388 +    int len = 0;
1389 +    if (name[0] != '.' || (namelen != 1 && (name[1] != '.' || namelen != 2))) {
1390 +        struct reiserfs_xattr_handler *xah = find_xattr_handler_prefix (name);
1391 +        if (!xah) return 0; /* Unsupported xattr name, skip it */
1392 +
1393 +        /* We call ->list() twice because the operation isn't required to just
1394 +         * return the name back - we want to make sure we have enough space */
1395 +        len += xah->list (b->r_inode, name, namelen, NULL);
1396 +
1397 +        if (len) {
1398 +            if (b->r_pos + len + 1 <= b->r_size) {
1399 +                char *p = b->r_buf + b->r_pos;
1400 +                p += xah->list (b->r_inode, name, namelen, p);
1401 +                *p++ = '\0';
1402 +            }
1403 +            b->r_pos += len + 1;
1404 +        }
1405 +    }
1406 +
1407 +    return 0;
1408 +}
1409 +/*
1410 + * Inode operation listxattr()
1411 + *
1412 + * dentry->d_inode->i_sem down
1413 + * BKL held [before 2.5.x]
1414 + */
1415 +ssize_t
1416 +reiserfs_listxattr (struct dentry *dentry, char *buffer, size_t size)
1417 +{
1418 +    struct file *fp;
1419 +    struct dentry *dir;
1420 +    int err = 0;
1421 +    struct reiserfs_listxattr_buf buf;
1422 +
1423 +    if (!dentry->d_inode)
1424 +        return -EINVAL;
1425 +
1426 +    if (!reiserfs_xattrs(dentry->d_sb) ||
1427 +        get_inode_sd_version (dentry->d_inode) == STAT_DATA_V1)
1428 +        return -EOPNOTSUPP;
1429 +
1430 +    reiserfs_read_lock_xattrs (dentry->d_sb);
1431 +    dir = open_xa_dir (dentry->d_inode, FL_READONLY);
1432 +    reiserfs_read_unlock_xattrs (dentry->d_sb);
1433 +    if (IS_ERR (dir)) {
1434 +        err = PTR_ERR (dir);
1435 +        if (err == -ENODATA)
1436 +            err = 0; /* Not an error if there aren't any xattrs */
1437 +        goto out;
1438 +    }
1439 +
1440 +    fp = dentry_open (dir, NULL, O_RDWR);
1441 +    if (IS_ERR (fp)) {
1442 +        err = PTR_ERR (fp);
1443 +        /* dentry_open dputs the dentry if it fails */
1444 +        goto out;
1445 +    }
1446 +
1447 +    buf.r_buf = buffer;
1448 +    buf.r_size = buffer ? size : 0;
1449 +    buf.r_pos = 0;
1450 +    buf.r_inode = dentry->d_inode;
1451 +
1452 +    err = xattr_readdir (fp, reiserfs_listxattr_filler, &buf);
1453 +    if (err)
1454 +        goto out_dir;
1455 +
1456 +    if (buf.r_pos > buf.r_size && buffer != NULL)
1457 +        err = -ERANGE;
1458 +    else
1459 +        err = buf.r_pos;
1460 +
1461 +out_dir:
1462 +    fput(fp);
1463 +
1464 +out:
1465 +    return err;
1466 +}
1467 +
1468 +/* This is the implementation for the xattr plugin infrastructure */
1469 +static struct reiserfs_xattr_handler *xattr_handlers;
1470 +static rwlock_t handler_lock = RW_LOCK_UNLOCKED;
1471 +
1472 +static struct reiserfs_xattr_handler *
1473 +find_xattr_handler_prefix (const char *prefix)
1474 +{
1475 +    struct reiserfs_xattr_handler **xah;
1476 +    read_lock (&handler_lock);
1477 +    for (xah = &xattr_handlers; *xah; xah=&(*xah)->next)
1478 +        if (strncmp ((*xah)->prefix, prefix, strlen ((*xah)->prefix)) == 0)
1479 +            break;
1480 +    read_unlock (&handler_lock);
1481 +    return *xah;
1482 +}
1483 +
1484 +int
1485 +reiserfs_xattr_register_handler (struct reiserfs_xattr_handler *handler)
1486 +{
1487 +    int res = 0;
1488 +    struct reiserfs_xattr_handler **xah;
1489 +
1490 +    if (!handler)
1491 +        return -EINVAL;
1492 +
1493 +    if (handler->next)
1494 +        return -EBUSY;
1495 +
1496 +    write_lock (&handler_lock);
1497 +
1498 +    for (xah = &xattr_handlers; *xah; xah=&(*xah)->next) {
1499 +        if (strcmp ((*xah)->prefix, handler->prefix) == 0)
1500 +            break;
1501 +    }
1502 +    if (*xah)
1503 +        res = -EBUSY;
1504 +    else
1505 +        *xah = handler;
1506 +
1507 +    /*
1508 +    if (!res)
1509 +        printk ("ReiserFS: Registered xattr handler for %s\n", handler->prefix);
1510 +    */
1511 +
1512 +    write_unlock (&handler_lock);
1513 +    return res;
1514 +}
1515 +
1516 +int
1517 +reiserfs_xattr_unregister_handler (struct reiserfs_xattr_handler *handler)
1518 +{
1519 +    struct reiserfs_xattr_handler **xah;
1520 +    write_lock (&handler_lock);
1521 +
1522 +    xah = &xattr_handlers;
1523 +    while (*xah) {
1524 +        if (handler == *xah) {
1525 +            *xah = handler->next;
1526 +            handler->next = NULL;
1527 +            write_unlock (&handler_lock);
1528 +            /*
1529 +            printk ("ReiserFS: Unregistered xattr handler for %s\n",
1530 +                    handler->prefix);
1531 +            */
1532 +            return 0;
1533 +        }
1534 +        xah = &(*xah)->next;
1535 +    }
1536 +    write_unlock (&handler_lock);
1537 +    return -EINVAL;
1538 +}
1539 +
1540 +/* We need to take a copy of the mount flags since things like
1541 + * MS_RDONLY don't get set until *after* we're called.
1542 + * mount_flags != mount_options */
1543 +
1544 +int
1545 +reiserfs_xattr_init (struct super_block *s, int mount_flags)
1546 +{
1547 +  int err = 0;
1548 +
1549 +  /* If the user has requested an optional xattrs type (e.g. user/acl), then
1550 +   * enable xattrs. If we're a v3.5 filesystem, this will get caught and
1551 +   * error out. If no optional xattrs are enabled, disable xattrs */
1552 +  if (reiserfs_xattrs_optional (s))
1553 +    set_bit (REISERFS_XATTRS, &(s->u.reiserfs_sb.s_mount_opt));
1554 +  else
1555 +    clear_bit (REISERFS_XATTRS, &(s->u.reiserfs_sb.s_mount_opt));
1556 +
1557 +  if (reiserfs_xattrs (s)) {
1558 +    /* We need generation numbers to ensure that the oid mapping is correct
1559 +     * v3.5 filesystems don't have them. */
1560 +    if (old_format_only (s)) {
1561 +      reiserfs_warning (s, "reiserfs: xattrs not supported on pre v3.6 "
1562 +                        "format filesystem. Failing mount.\n");
1563 +      err = -EOPNOTSUPP;
1564 +      goto error;
1565 +    } else if (!s->u.reiserfs_sb.priv_root) {
1566 +      struct dentry *dentry;
1567 +      dentry = lookup_one_len (PRIVROOT_NAME, s->s_root,
1568 +                               strlen (PRIVROOT_NAME));
1569 +      if (!IS_ERR (dentry)) {
1570 +        if (!(mount_flags & MS_RDONLY) && !dentry->d_inode) {
1571 +            struct inode *inode = dentry->d_parent->d_inode;
1572 +            down (&inode->i_sem);
1573 +            err = inode->i_op->mkdir (inode, dentry, 0700);
1574 +            up (&inode->i_sem);
1575 +            if (err) {
1576 +                dput (dentry);
1577 +                dentry = NULL;
1578 +            }
1579 +
1580 +            if (dentry && dentry->d_inode)
1581 +                reiserfs_warning (inode->i_sb, "reiserfs: Created %s on %s - reserved for "
1582 +                                  "xattr storage.\n", PRIVROOT_NAME, 
1583 +                                  bdevname (inode->i_sb->s_dev));
1584 +        } else if (!dentry->d_inode) {
1585 +            dput (dentry);
1586 +            dentry = NULL;
1587 +        }
1588 +      } else
1589 +        err = PTR_ERR (dentry);
1590 +
1591 +      if (!err && dentry) {
1592 +          d_drop (dentry);
1593 +          dentry->d_inode->u.reiserfs_i.i_flags |= i_priv_object;
1594 +          s->u.reiserfs_sb.priv_root = dentry;
1595 +      } else { /* xattrs are unavailable */
1596 +          /* If we're read-only it just means that the dir hasn't been
1597 +           * created. Not an error -- just no xattrs on the fs. We'll
1598 +           * check again if we go read-write */
1599 +          if (!(mount_flags & MS_RDONLY)) {
1600 +              reiserfs_warning (s, "reiserfs: xattrs enabled and couldn't "
1601 +                             "find/create .reiserfs_priv. Failing mount.\n");
1602 +            err = -EOPNOTSUPP;
1603 +            goto error;
1604 +          }
1605 +          /* Just to speed things up a bit since it won't find anything and
1606 +           * we're read-only */
1607 +          clear_bit (REISERFS_XATTRS, &(s->u.reiserfs_sb.s_mount_opt));
1608 +          clear_bit (REISERFS_XATTRS_USER, &(s->u.reiserfs_sb.s_mount_opt));
1609 +      }
1610 +    }
1611 +  }
1612 +
1613 +error:
1614 +   /* This is only nonzero if there was an error initializing the xattr
1615 +    * directory or if there is a condition where we don't support them. */
1616 +
1617 +    if (err) {
1618 +          clear_bit (REISERFS_XATTRS, &(s->u.reiserfs_sb.s_mount_opt));
1619 +          clear_bit (REISERFS_XATTRS_USER, &(s->u.reiserfs_sb.s_mount_opt));
1620 +    }
1621 +    return err;
1622 +}
1623 diff -ruNp -X ../dontdiff linux-2.4.23.datalogging+quota/fs/reiserfs/xattr_user.c linux-2.4.23.xattr/fs/reiserfs/xattr_user.c
1624 --- linux-2.4.23.datalogging+quota/fs/reiserfs/xattr_user.c     1969-12-31 19:00:00.000000000 -0500
1625 +++ linux-2.4.23.xattr/fs/reiserfs/xattr_user.c 2003-12-11 12:55:03.333492824 -0500
1626 @@ -0,0 +1,108 @@
1627 +#include <linux/reiserfs_fs.h>
1628 +#include <linux/errno.h>
1629 +#include <linux/fs.h>
1630 +#include <linux/pagemap.h>
1631 +#include <linux/xattr.h>
1632 +#include <linux/reiserfs_xattr.h>
1633 +#include <asm/uaccess.h>
1634 +
1635 +#define XATTR_USER_PREFIX "user."
1636 +
1637 +static int
1638 +user_get (struct inode *inode, const char *name, void *buffer, size_t size)
1639 +{
1640 +
1641 +    int error;
1642 +
1643 +    if (strlen(name) < sizeof(XATTR_USER_PREFIX))
1644 +        return -EINVAL;
1645 +
1646 +    if (!reiserfs_xattrs_user (inode->i_sb))
1647 +        return -EOPNOTSUPP;
1648 +
1649 +    error = permission (inode, MAY_READ);
1650 +    if (error)
1651 +        return error;
1652 +
1653 +    return reiserfs_xattr_get (inode, name, buffer, size);
1654 +}
1655 +
1656 +static int
1657 +user_set (struct inode *inode, const char *name, const void *buffer,
1658 +          size_t size, int flags)
1659 +{
1660 +
1661 +    int error;
1662 +
1663 +    if (strlen(name) < sizeof(XATTR_USER_PREFIX))
1664 +        return -EINVAL;
1665 +
1666 +    if (!reiserfs_xattrs_user (inode->i_sb))
1667 +        return -EOPNOTSUPP;
1668 +
1669 +    if (!S_ISREG (inode->i_mode) &&
1670 +        (!S_ISDIR (inode->i_mode) || inode->i_mode & S_ISVTX))
1671 +        return -EPERM;
1672 +
1673 +    error = permission (inode, MAY_WRITE);
1674 +    if (error)
1675 +        return error;
1676 +
1677 +    return reiserfs_xattr_set (inode, name, buffer, size, flags);
1678 +}
1679 +
1680 +static int
1681 +user_del (struct inode *inode, const char *name)
1682 +{
1683 +    int error;
1684 +
1685 +    if (strlen(name) < sizeof(XATTR_USER_PREFIX))
1686 +        return -EINVAL;
1687 +
1688 +    if (!reiserfs_xattrs_user (inode->i_sb))
1689 +        return -EOPNOTSUPP;
1690 +
1691 +    if (!S_ISREG (inode->i_mode) &&
1692 +        (!S_ISDIR (inode->i_mode) || inode->i_mode & S_ISVTX))
1693 +        return -EPERM;
1694 +
1695 +    error = permission (inode, MAY_WRITE);
1696 +    if (error)
1697 +        return error;
1698 +
1699 +    return 0;
1700 +}
1701 +
1702 +static int
1703 +user_list (struct inode *inode, const char *name, int namelen, char *out)
1704 +{
1705 +    int len = namelen;
1706 +    if (!reiserfs_xattrs_user (inode->i_sb))
1707 +        return 0;
1708 +
1709 +    if (out)
1710 +        memcpy (out, name, len);
1711 +
1712 +    return len;
1713 +}
1714 +
1715 +
1716 +struct reiserfs_xattr_handler user_handler = {
1717 +    prefix: XATTR_USER_PREFIX,
1718 +    get: user_get,
1719 +    set: user_set,
1720 +    del: user_del,
1721 +    list: user_list,
1722 +};
1723 +
1724 +int __init
1725 +reiserfs_xattr_user_init (void)
1726 +{
1727 +    return reiserfs_xattr_register_handler (&user_handler);
1728 +}
1729 +
1730 +int
1731 +reiserfs_xattr_user_exit (void)
1732 +{
1733 +    return reiserfs_xattr_unregister_handler (&user_handler);
1734 +}
1735 diff -ruNp -X ../dontdiff linux-2.4.23.datalogging+quota/include/linux/reiserfs_fs.h linux-2.4.23.xattr/include/linux/reiserfs_fs.h
1736 --- linux-2.4.23.datalogging+quota/include/linux/reiserfs_fs.h  2003-12-11 12:54:29.715603520 -0500
1737 +++ linux-2.4.23.xattr/include/linux/reiserfs_fs.h      2003-12-11 12:55:03.335492520 -0500
1738 @@ -2012,6 +2012,7 @@ static inline void reiserfs_update_sd(st
1739  
1740  void sd_attrs_to_i_attrs( __u16 sd_attrs, struct inode *inode );
1741  void i_attrs_to_sd_attrs( struct inode *inode, __u16 *sd_attrs );
1742 +int reiserfs_setattr(struct dentry *dentry, struct iattr *attr);
1743  
1744  /* namei.c */
1745  inline void set_de_name_and_namelen (struct reiserfs_dir_entry * de);
1746 @@ -2081,6 +2082,7 @@ int reiserfs_journal_in_proc( char *buff
1747  
1748  /* dir.c */
1749  extern struct inode_operations reiserfs_dir_inode_operations;
1750 +extern struct inode_operations reiserfs_symlink_inode_operations;
1751  extern struct file_operations reiserfs_dir_operations;
1752  
1753  /* tail_conversion.c */
1754 @@ -2301,6 +2303,9 @@ int reiserfs_unpack (struct inode * inod
1755  #define REISERFS_IOC_GETVERSION        EXT2_IOC_GETVERSION
1756  #define REISERFS_IOC_SETVERSION         EXT2_IOC_SETVERSION
1757                                  
1758 +/* xattr stuff */
1759 +#define REISERFS_XATTR_DIR_SEM(s) ((s)->u.reiserfs_sb.xattr_dir_sem)
1760 +
1761  #endif /* _LINUX_REISER_FS_H */
1762  
1763  
1764 diff -ruNp -X ../dontdiff linux-2.4.23.datalogging+quota/include/linux/reiserfs_fs_i.h linux-2.4.23.xattr/include/linux/reiserfs_fs_i.h
1765 --- linux-2.4.23.datalogging+quota/include/linux/reiserfs_fs_i.h        2003-12-11 12:54:15.944697016 -0500
1766 +++ linux-2.4.23.xattr/include/linux/reiserfs_fs_i.h    2003-12-11 12:55:03.335492520 -0500
1767 @@ -28,6 +28,7 @@ typedef enum {
1768      i_link_saved_truncate_mask =  0x0020,
1769      /** are we logging data blocks for this file? */
1770      i_data_log                 =  0x0040,
1771 +    i_priv_object              =  0x0080,
1772  } reiserfs_inode_flags;
1773  
1774  
1775 diff -ruNp -X ../dontdiff linux-2.4.23.datalogging+quota/include/linux/reiserfs_fs_sb.h linux-2.4.23.xattr/include/linux/reiserfs_fs_sb.h
1776 --- linux-2.4.23.datalogging+quota/include/linux/reiserfs_fs_sb.h       2003-12-11 12:54:15.945696864 -0500
1777 +++ linux-2.4.23.xattr/include/linux/reiserfs_fs_sb.h   2003-12-11 12:55:03.336492368 -0500
1778 @@ -6,6 +6,7 @@
1779  
1780  #ifdef __KERNEL__
1781  #include <linux/tqueue.h>
1782 +#include <linux/rwsem.h>
1783  #endif
1784  
1785  //
1786 @@ -442,6 +443,9 @@ struct reiserfs_sb_info
1787      struct proc_dir_entry *procdir;
1788      int reserved_blocks; /* amount of blocks reserved for further allocations */
1789      struct list_head s_reiserfs_supers;
1790 +    struct dentry *priv_root; /* root of /.reiserfs_priv */
1791 +    struct dentry *xattr_root; /* root of /.reiserfs_priv/.xa */
1792 +    struct rw_semaphore xattr_dir_sem;
1793  };
1794  
1795  /* Definitions of reiserfs on-disk properties: */
1796 @@ -486,6 +490,8 @@ enum {
1797      REISERFS_DATA_WRITEBACK,
1798      REISERFS_ATTRS,
1799      REISERFS_TEST4,
1800 +    REISERFS_XATTRS,
1801 +    REISERFS_XATTRS_USER,
1802  };
1803  
1804  #define reiserfs_r5_hash(s) ((s)->u.reiserfs_sb.s_mount_opt & (1 << FORCE_R5_HASH))
1805 @@ -507,6 +513,9 @@ enum {
1806  #define reiserfs_attrs(s) ((s)->u.reiserfs_sb.s_mount_opt & (1 << REISERFS_ATTRS))
1807  #define old_format_only(s) ((s)->u.reiserfs_sb.s_properties & (1 << REISERFS_3_5))
1808  #define convert_reiserfs(s) ((s)->u.reiserfs_sb.s_mount_opt & (1 << REISERFS_CONVERT))
1809 +#define reiserfs_xattrs(s) ((s)->u.reiserfs_sb.s_mount_opt & (1 << REISERFS_XATTRS))
1810 +#define reiserfs_xattrs_user(s) ((s)->u.reiserfs_sb.s_mount_opt & (1 << REISERFS_XATTRS_USER))
1811 +#define reiserfs_xattrs_optional(s) reiserfs_xattrs_user(s)
1812  
1813  
1814  void reiserfs_file_buffer (struct buffer_head * bh, int list);
1815 diff -ruNp -X ../dontdiff linux-2.4.23.datalogging+quota/include/linux/reiserfs_xattr.h linux-2.4.23.xattr/include/linux/reiserfs_xattr.h
1816 --- linux-2.4.23.datalogging+quota/include/linux/reiserfs_xattr.h       1969-12-31 19:00:00.000000000 -0500
1817 +++ linux-2.4.23.xattr/include/linux/reiserfs_xattr.h   2003-12-11 12:55:03.337492216 -0500
1818 @@ -0,0 +1,114 @@
1819 +/*
1820 +  File: linux/reiserfs_xattr.h
1821 +*/
1822 +
1823 +#include <linux/config.h>
1824 +#include <linux/init.h>
1825 +#include <linux/xattr.h>
1826 +
1827 +/* Magic value in header */
1828 +#define REISERFS_XATTR_MAGIC 0x52465841 /* "RFXA" */
1829 +
1830 +struct reiserfs_xattr_header {
1831 +    __u32 h_magic;              /* magic number for identification */
1832 +    __u32 h_hash;               /* hash of the value */
1833 +};
1834 +
1835 +#ifdef __KERNEL__
1836 +
1837 +struct reiserfs_xattr_handler {
1838 +       char *prefix;
1839 +       int (*get)(struct inode *inode, const char *name, void *buffer,
1840 +                  size_t size);
1841 +       int (*set)(struct inode *inode, const char *name, const void *buffer,
1842 +                  size_t size, int flags);
1843 +       int (*del)(struct inode *inode, const char *name);
1844 +        int (*list)(struct inode *inode, const char *name, int namelen, char *out);
1845 +        struct reiserfs_xattr_handler *next;
1846 +};
1847 +
1848 +
1849 +#ifdef CONFIG_REISERFS_FS_XATTR
1850 +#define is_reiserfs_priv_object(inode) (((inode)->u.reiserfs_i.i_flags & i_priv_object) == i_priv_object)
1851 +ssize_t reiserfs_getxattr (struct dentry *dentry, const char *name,
1852 +                          void *buffer, size_t size);
1853 +int reiserfs_setxattr (struct dentry *dentry, const char *name,
1854 +                       const void *value, size_t size, int flags);
1855 +ssize_t reiserfs_listxattr (struct dentry *dentry, char *buffer, size_t size);
1856 +int reiserfs_removexattr (struct dentry *dentry, const char *name);
1857 +int reiserfs_delete_xattrs (struct inode *inode);
1858 +int reiserfs_chown_xattrs (struct inode *inode, struct iattr *attrs);
1859 +int reiserfs_xattr_init (struct super_block *sb, int mount_flags);
1860 +
1861 +static inline void
1862 +reiserfs_write_lock_xattrs(struct super_block *sb)
1863 +{
1864 +    down_write (&REISERFS_XATTR_DIR_SEM(sb));
1865 +}
1866 +static inline void
1867 +reiserfs_write_unlock_xattrs(struct super_block *sb)
1868 +{
1869 +    up_write (&REISERFS_XATTR_DIR_SEM(sb));
1870 +}
1871 +static inline void
1872 +reiserfs_read_lock_xattrs(struct super_block *sb)
1873 +{
1874 +    down_read (&REISERFS_XATTR_DIR_SEM(sb));
1875 +}
1876 +static inline void
1877 +reiserfs_read_unlock_xattrs(struct super_block *sb)
1878 +{
1879 +    up_read (&REISERFS_XATTR_DIR_SEM(sb));
1880 +}
1881 +#else
1882 +#define is_reiserfs_priv_object(inode) 0
1883 +#define reiserfs_getxattr NULL
1884 +#define reiserfs_setxattr NULL
1885 +#define reiserfs_listxattr NULL
1886 +#define reiserfs_removexattr NULL
1887 +#define reiserfs_write_lock_xattrs(sb)
1888 +#define reiserfs_write_unlock_xattrs(sb)
1889 +#define reiserfs_read_lock_xattrs(sb)
1890 +#define reiserfs_read_unlock_xattrs(sb)
1891 +static inline int
1892 +reiserfs_xattr_init (struct super_block *s, int mount_flags)
1893 +{
1894 +    return 0;
1895 +}
1896 +
1897 +static inline int
1898 +reiserfs_delete_xattrs (struct inode *inode)
1899 +{
1900 +    return 0;
1901 +}
1902 +
1903 +static inline int
1904 +reiserfs_chown_xattrs (struct inode *inode, struct iattr *attrs)
1905 +{
1906 +    return 0;
1907 +}
1908 +#endif
1909 +
1910 +extern int reiserfs_xattr_register_handler(struct reiserfs_xattr_handler *);
1911 +extern int reiserfs_xattr_unregister_handler(struct reiserfs_xattr_handler *);
1912 +extern int reiserfs_xattr_del (struct inode *, const char *);
1913 +extern int reiserfs_xattr_get (const struct inode *, const char *, void *, size_t);
1914 +extern int reiserfs_xattr_set (struct inode *, const char *, const void *,
1915 +                               size_t, int);
1916 +#ifdef CONFIG_REISERFS_FS_XATTR_USER
1917 +extern int reiserfs_xattr_user_init (void) __init;
1918 +extern int reiserfs_xattr_user_exit (void);
1919 +#else
1920 +static inline int
1921 +reiserfs_xattr_user_init (void)
1922 +{
1923 +    return 0;
1924 +}
1925 +
1926 +static inline int
1927 +reiserfs_xattr_user_exit (void)
1928 +{
1929 +    return 0;
1930 +}
1931 +#endif
1932 +#endif  /* __KERNEL__ */
This page took 0.184626 seconds and 3 git commands to generate.