]>
Commit | Line | Data |
---|---|---|
2416a217 JR |
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) { | |
d871ed22 | 176 | + reiserfs_warning (inode->i_sb, "ACLs aren't enabled in the fs, but vfs thinks they are!\n"); |
2416a217 JR |
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 | |
d871ed22 | 563 | @@ -9,6 +9,9 @@ |
2416a217 JR |
564 | #include <linux/vmalloc.h> |
565 | #include <asm/uaccess.h> | |
566 | #include <linux/reiserfs_fs.h> | |
d871ed22 | 567 | +#include <linux/reiserfs_fs_sb.h> |
2416a217 JR |
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)) { | |
d871ed22 | 1101 | +reiserfs_warning(inode->i_sb, "not direntry %h\n", ih); |
2416a217 JR |
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)) { | |
d871ed22 | 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)); |
2416a217 JR |
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 { | |
d871ed22 | 1574 | + reiserfs_warning (inode->i_sb, "Couldn't remove all entries in directory\n"); |
2416a217 JR |
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)) { | |
d871ed22 | 1963 | + reiserfs_warning (s, "reiserfs: xattrs/ACLs not supported on pre v3.6 " |
2416a217 JR |
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) | |
d871ed22 | 1983 | + reiserfs_warning (s, "reiserfs: Created %s on %s - reserved for " |
2416a217 JR |
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)) { | |
d871ed22 | 1999 | + reiserfs_warning (s, "reiserfs: xattrs/ACLs enabled and couldn't " |
2416a217 JR |
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__ */ |