]>
Commit | Line | Data |
---|---|---|
51560e02 AM |
1 | diff -urN linux-2.4.22.org/arch/alpha/defconfig linux-2.4.22/arch/alpha/defconfig |
2 | --- linux-2.4.22.org/arch/alpha/defconfig 2003-11-21 15:04:31.000000000 +0100 | |
3 | +++ linux-2.4.22/arch/alpha/defconfig 2003-11-21 15:26:23.000000000 +0100 | |
4 | @@ -554,6 +554,10 @@ | |
e57e653a JR |
5 | # CONFIG_AUTOFS4_FS is not set |
6 | CONFIG_REISERFS_FS=m | |
7 | # CONFIG_REISERFS_CHECK is not set | |
8 | +# CONFIG_REISERFS_FS_XATTR is not set | |
9 | +# CONFIG_REISERFS_FS_XATTR_USER is not set | |
10 | +# CONFIG_REISERFS_FS_XATTR_SHARING is not set | |
11 | +# CONFIG_REISERFS_FS_POSIX_ACL is not set | |
12 | # CONFIG_ADFS_FS is not set | |
13 | # CONFIG_ADFS_FS_RW is not set | |
14 | # CONFIG_AFFS_FS is not set | |
51560e02 AM |
15 | diff -urN linux-2.4.22.org/arch/i386/config.in linux-2.4.22/arch/i386/config.in |
16 | --- linux-2.4.22.org/arch/i386/config.in 2003-11-21 15:04:28.000000000 +0100 | |
17 | +++ linux-2.4.22/arch/i386/config.in 2003-11-21 15:26:23.000000000 +0100 | |
e57e653a JR |
18 | @@ -74,6 +74,7 @@ |
19 | define_bool CONFIG_X86_F00F_WORKS_OK n | |
20 | fi | |
21 | if [ "$CONFIG_M586" = "y" ]; then | |
22 | + define_bool CONFIG_X86_CMPXCHG8 y | |
23 | define_int CONFIG_X86_L1_CACHE_SHIFT 5 | |
24 | define_bool CONFIG_X86_USE_STRING_486 y | |
25 | define_bool CONFIG_X86_ALIGNMENT_16 y | |
26 | @@ -81,6 +82,7 @@ | |
27 | define_bool CONFIG_X86_F00F_WORKS_OK n | |
28 | fi | |
29 | if [ "$CONFIG_M586TSC" = "y" ]; then | |
30 | + define_bool CONFIG_X86_CMPXCHG8 y | |
31 | define_int CONFIG_X86_L1_CACHE_SHIFT 5 | |
32 | define_bool CONFIG_X86_USE_STRING_486 y | |
33 | define_bool CONFIG_X86_ALIGNMENT_16 y | |
34 | @@ -89,6 +91,7 @@ | |
35 | define_bool CONFIG_X86_F00F_WORKS_OK n | |
36 | fi | |
37 | if [ "$CONFIG_M586MMX" = "y" ]; then | |
38 | + define_bool CONFIG_X86_CMPXCHG8 y | |
39 | define_int CONFIG_X86_L1_CACHE_SHIFT 5 | |
40 | define_bool CONFIG_X86_USE_STRING_486 y | |
41 | define_bool CONFIG_X86_ALIGNMENT_16 y | |
42 | @@ -98,6 +101,7 @@ | |
43 | define_bool CONFIG_X86_F00F_WORKS_OK n | |
44 | fi | |
45 | if [ "$CONFIG_M686" = "y" ]; then | |
46 | + define_bool CONFIG_X86_CMPXCHG8 y | |
47 | define_int CONFIG_X86_L1_CACHE_SHIFT 5 | |
48 | define_bool CONFIG_X86_HAS_TSC y | |
49 | define_bool CONFIG_X86_GOOD_APIC y | |
50 | @@ -107,6 +111,7 @@ | |
51 | define_bool CONFIG_X86_F00F_WORKS_OK y | |
52 | fi | |
53 | if [ "$CONFIG_MPENTIUMIII" = "y" ]; then | |
54 | + define_bool CONFIG_X86_CMPXCHG8 y | |
55 | define_int CONFIG_X86_L1_CACHE_SHIFT 5 | |
56 | define_bool CONFIG_X86_HAS_TSC y | |
57 | define_bool CONFIG_X86_GOOD_APIC y | |
51560e02 AM |
58 | @@ -115,6 +120,7 @@ |
59 | define_bool CONFIG_X86_F00F_WORKS_OK y | |
e57e653a JR |
60 | fi |
61 | if [ "$CONFIG_MPENTIUM4" = "y" ]; then | |
62 | + define_bool CONFIG_X86_CMPXCHG8 y | |
63 | define_int CONFIG_X86_L1_CACHE_SHIFT 7 | |
64 | define_bool CONFIG_X86_HAS_TSC y | |
65 | define_bool CONFIG_X86_GOOD_APIC y | |
51560e02 AM |
66 | @@ -123,6 +129,7 @@ |
67 | define_bool CONFIG_X86_F00F_WORKS_OK y | |
e57e653a JR |
68 | fi |
69 | if [ "$CONFIG_MK6" = "y" ]; then | |
70 | + define_bool CONFIG_X86_CMPXCHG8 y | |
71 | define_int CONFIG_X86_L1_CACHE_SHIFT 5 | |
72 | define_bool CONFIG_X86_ALIGNMENT_16 y | |
73 | define_bool CONFIG_X86_HAS_TSC y | |
51560e02 | 74 | @@ -134,6 +141,7 @@ |
e57e653a JR |
75 | define_bool CONFIG_MK7 y |
76 | fi | |
77 | if [ "$CONFIG_MK7" = "y" ]; then | |
78 | + define_bool CONFIG_X86_CMPXCHG8 y | |
79 | define_int CONFIG_X86_L1_CACHE_SHIFT 6 | |
80 | define_bool CONFIG_X86_HAS_TSC y | |
81 | define_bool CONFIG_X86_GOOD_APIC y | |
51560e02 AM |
82 | diff -urN linux-2.4.22.org/arch/ia64/defconfig linux-2.4.22/arch/ia64/defconfig |
83 | --- linux-2.4.22.org/arch/ia64/defconfig 2003-11-21 15:04:31.000000000 +0100 | |
84 | +++ linux-2.4.22/arch/ia64/defconfig 2003-11-21 15:26:23.000000000 +0100 | |
85 | @@ -684,6 +684,10 @@ | |
e57e653a JR |
86 | # CONFIG_REISERFS_FS is not set |
87 | # CONFIG_REISERFS_CHECK is not set | |
88 | # CONFIG_REISERFS_PROC_INFO is not set | |
89 | +# CONFIG_REISERFS_FS_XATTR is not set | |
90 | +# CONFIG_REISERFS_FS_XATTR_USER is not set | |
91 | +# CONFIG_REISERFS_FS_XATTR_SHARING is not set | |
92 | +# CONFIG_REISERFS_FS_POSIX_ACL is not set | |
93 | # CONFIG_ADFS_FS is not set | |
94 | # CONFIG_ADFS_FS_RW is not set | |
95 | # CONFIG_AFFS_FS is not set | |
51560e02 AM |
96 | diff -urN linux-2.4.22.org/arch/mips/defconfig linux-2.4.22/arch/mips/defconfig |
97 | --- linux-2.4.22.org/arch/mips/defconfig 2003-11-21 15:04:30.000000000 +0100 | |
98 | +++ linux-2.4.22/arch/mips/defconfig 2003-11-21 15:26:23.000000000 +0100 | |
99 | @@ -524,6 +524,10 @@ | |
e57e653a JR |
100 | # CONFIG_REISERFS_FS is not set |
101 | # CONFIG_REISERFS_CHECK is not set | |
102 | # CONFIG_REISERFS_PROC_INFO is not set | |
103 | +# CONFIG_REISERFS_FS_XATTR is not set | |
104 | +# CONFIG_REISERFS_FS_XATTR_USER is not set | |
105 | +# CONFIG_REISERFS_FS_XATTR_SHARING is not set | |
106 | +# CONFIG_REISERFS_FS_POSIX_ACL is not set | |
107 | # CONFIG_ADFS_FS is not set | |
108 | # CONFIG_ADFS_FS_RW is not set | |
109 | # CONFIG_AFFS_FS is not set | |
51560e02 AM |
110 | diff -urN linux-2.4.22.org/arch/mips64/defconfig linux-2.4.22/arch/mips64/defconfig |
111 | --- linux-2.4.22.org/arch/mips64/defconfig 2003-11-21 15:04:30.000000000 +0100 | |
112 | +++ linux-2.4.22/arch/mips64/defconfig 2003-11-21 15:26:23.000000000 +0100 | |
e57e653a JR |
113 | @@ -489,6 +489,10 @@ |
114 | # CONFIG_REISERFS_FS is not set | |
115 | # CONFIG_REISERFS_CHECK is not set | |
116 | # CONFIG_REISERFS_PROC_INFO is not set | |
117 | +# CONFIG_REISERFS_FS_XATTR is not set | |
118 | +# CONFIG_REISERFS_FS_XATTR_USER is not set | |
119 | +# CONFIG_REISERFS_FS_XATTR_SHARING is not set | |
120 | +# CONFIG_REISERFS_FS_POSIX_ACL is not set | |
121 | # CONFIG_ADFS_FS is not set | |
122 | # CONFIG_ADFS_FS_RW is not set | |
123 | # CONFIG_AFFS_FS is not set | |
51560e02 AM |
124 | diff -urN linux-2.4.22.org/arch/ppc/defconfig linux-2.4.22/arch/ppc/defconfig |
125 | --- linux-2.4.22.org/arch/ppc/defconfig 2003-11-21 15:04:31.000000000 +0100 | |
126 | +++ linux-2.4.22/arch/ppc/defconfig 2003-11-21 15:26:23.000000000 +0100 | |
127 | @@ -766,6 +766,10 @@ | |
e57e653a JR |
128 | # CONFIG_REISERFS_FS is not set |
129 | # CONFIG_REISERFS_CHECK is not set | |
130 | # CONFIG_REISERFS_PROC_INFO is not set | |
131 | +# CONFIG_REISERFS_FS_XATTR is not set | |
132 | +# CONFIG_REISERFS_FS_XATTR_USER is not set | |
133 | +# CONFIG_REISERFS_FS_XATTR_SHARING is not set | |
134 | +# CONFIG_REISERFS_FS_POSIX_ACL is not set | |
135 | # CONFIG_ADFS_FS is not set | |
136 | # CONFIG_ADFS_FS_RW is not set | |
137 | # CONFIG_AFFS_FS is not set | |
51560e02 AM |
138 | diff -urN linux-2.4.22.org/arch/ppc64/defconfig linux-2.4.22/arch/ppc64/defconfig |
139 | --- linux-2.4.22.org/arch/ppc64/defconfig 2003-11-21 15:04:30.000000000 +0100 | |
140 | +++ linux-2.4.22/arch/ppc64/defconfig 2003-11-21 15:26:23.000000000 +0100 | |
e57e653a JR |
141 | @@ -593,6 +593,10 @@ |
142 | CONFIG_REISERFS_FS=y | |
143 | # CONFIG_REISERFS_CHECK is not set | |
144 | # CONFIG_REISERFS_PROC_INFO is not set | |
145 | +# CONFIG_REISERFS_FS_XATTR is not set | |
146 | +# CONFIG_REISERFS_FS_XATTR_USER is not set | |
147 | +# CONFIG_REISERFS_FS_XATTR_SHARING is not set | |
148 | +# CONFIG_REISERFS_FS_POSIX_ACL is not set | |
149 | # CONFIG_ADFS_FS is not set | |
150 | # CONFIG_ADFS_FS_RW is not set | |
151 | # CONFIG_AFFS_FS is not set | |
51560e02 AM |
152 | diff -urN linux-2.4.22.org/arch/s390/defconfig linux-2.4.22/arch/s390/defconfig |
153 | --- linux-2.4.22.org/arch/s390/defconfig 2003-11-21 15:04:31.000000000 +0100 | |
154 | +++ linux-2.4.22/arch/s390/defconfig 2003-11-21 15:26:23.000000000 +0100 | |
e57e653a JR |
155 | @@ -282,6 +282,10 @@ |
156 | # CONFIG_REISERFS_FS is not set | |
157 | # CONFIG_REISERFS_CHECK is not set | |
158 | # CONFIG_REISERFS_PROC_INFO is not set | |
159 | +# CONFIG_REISERFS_FS_XATTR is not set | |
160 | +# CONFIG_REISERFS_FS_XATTR_USER is not set | |
161 | +# CONFIG_REISERFS_FS_XATTR_SHARING is not set | |
162 | +# CONFIG_REISERFS_FS_POSIX_ACL is not set | |
163 | # CONFIG_ADFS_FS is not set | |
164 | # CONFIG_ADFS_FS_RW is not set | |
165 | # CONFIG_AFFS_FS is not set | |
51560e02 AM |
166 | diff -urN linux-2.4.22.org/arch/s390x/defconfig linux-2.4.22/arch/s390x/defconfig |
167 | --- linux-2.4.22.org/arch/s390x/defconfig 2003-11-21 15:04:30.000000000 +0100 | |
168 | +++ linux-2.4.22/arch/s390x/defconfig 2003-11-21 15:26:23.000000000 +0100 | |
e57e653a JR |
169 | @@ -224,6 +224,10 @@ |
170 | # CONFIG_REISERFS_FS is not set | |
171 | # CONFIG_REISERFS_CHECK is not set | |
172 | # CONFIG_REISERFS_PROC_INFO is not set | |
173 | +# CONFIG_REISERFS_FS_XATTR is not set | |
174 | +# CONFIG_REISERFS_FS_XATTR_USER is not set | |
175 | +# CONFIG_REISERFS_FS_XATTR_SHARING is not set | |
176 | +# CONFIG_REISERFS_FS_POSIX_ACL is not set | |
177 | # CONFIG_ADFS_FS is not set | |
178 | # CONFIG_ADFS_FS_RW is not set | |
179 | # CONFIG_AFFS_FS is not set | |
51560e02 AM |
180 | diff -urN linux-2.4.22.org/arch/sparc/defconfig linux-2.4.22/arch/sparc/defconfig |
181 | --- linux-2.4.22.org/arch/sparc/defconfig 2003-11-21 15:04:30.000000000 +0100 | |
182 | +++ linux-2.4.22/arch/sparc/defconfig 2003-11-21 15:26:23.000000000 +0100 | |
183 | @@ -294,6 +294,10 @@ | |
e57e653a JR |
184 | # CONFIG_REISERFS_FS is not set |
185 | # CONFIG_REISERFS_CHECK is not set | |
186 | # CONFIG_REISERFS_PROC_INFO is not set | |
187 | +# CONFIG_REISERFS_FS_XATTR is not set | |
188 | +# CONFIG_REISERFS_FS_XATTR_USER is not set | |
189 | +# CONFIG_REISERFS_FS_XATTR_SHARING is not set | |
190 | +# CONFIG_REISERFS_FS_POSIX_ACL is not set | |
191 | # CONFIG_ADFS_FS is not set | |
192 | # CONFIG_ADFS_FS_RW is not set | |
193 | CONFIG_AFFS_FS=m | |
51560e02 AM |
194 | diff -urN linux-2.4.22.org/arch/sparc64/defconfig linux-2.4.22/arch/sparc64/defconfig |
195 | --- linux-2.4.22.org/arch/sparc64/defconfig 2003-11-21 15:04:30.000000000 +0100 | |
196 | +++ linux-2.4.22/arch/sparc64/defconfig 2003-11-21 15:26:23.000000000 +0100 | |
197 | @@ -738,6 +738,10 @@ | |
e57e653a JR |
198 | # CONFIG_REISERFS_FS is not set |
199 | # CONFIG_REISERFS_CHECK is not set | |
200 | # CONFIG_REISERFS_PROC_INFO is not set | |
201 | +# CONFIG_REISERFS_FS_XATTR is not set | |
202 | +# CONFIG_REISERFS_FS_XATTR_USER is not set | |
203 | +# CONFIG_REISERFS_FS_XATTR_SHARING is not set | |
204 | +# CONFIG_REISERFS_FS_POSIX_ACL is not set | |
205 | # CONFIG_ADFS_FS is not set | |
206 | # CONFIG_ADFS_FS_RW is not set | |
207 | CONFIG_AFFS_FS=m | |
51560e02 AM |
208 | diff -urN linux-2.4.22.org/fs/Config.in linux-2.4.22/fs/Config.in |
209 | --- linux-2.4.22.org/fs/Config.in 2003-11-21 15:04:31.000000000 +0100 | |
210 | +++ linux-2.4.22/fs/Config.in 2003-11-21 15:26:23.000000000 +0100 | |
e57e653a JR |
211 | @@ -13,6 +13,10 @@ |
212 | tristate 'Reiserfs support' CONFIG_REISERFS_FS | |
213 | dep_mbool ' Enable reiserfs debug mode' CONFIG_REISERFS_CHECK $CONFIG_REISERFS_FS | |
214 | dep_mbool ' Stats in /proc/fs/reiserfs' CONFIG_REISERFS_PROC_INFO $CONFIG_REISERFS_FS | |
215 | +dep_mbool ' ReiserFS extended attributes' CONFIG_REISERFS_FS_XATTR $CONFIG_REISERFS_FS | |
216 | +dep_mbool ' ReiserFS extended user attributes' CONFIG_REISERFS_FS_XATTR_USER $CONFIG_REISERFS_FS_XATTR | |
217 | +dep_mbool ' ReiserFS trusted extended attributes' CONFIG_REISERFS_FS_XATTR_TRUSTED $CONFIG_REISERFS_FS_XATTR | |
218 | +dep_mbool ' ReiserFS POSIX Access Control Lists' CONFIG_REISERFS_FS_POSIX_ACL $CONFIG_REISERFS_FS_XATTR $CONFIG_FS_POSIX_ACL | |
219 | ||
220 | dep_tristate 'ADFS file system support (EXPERIMENTAL)' CONFIG_ADFS_FS $CONFIG_EXPERIMENTAL | |
221 | dep_mbool ' ADFS write support (DANGEROUS)' CONFIG_ADFS_FS_RW $CONFIG_ADFS_FS $CONFIG_EXPERIMENTAL | |
51560e02 AM |
222 | diff -urN linux-2.4.22.org/fs/inode.c linux-2.4.22/fs/inode.c |
223 | --- linux-2.4.22.org/fs/inode.c 2003-11-21 15:14:23.000000000 +0100 | |
224 | +++ linux-2.4.22/fs/inode.c 2003-11-21 15:26:23.000000000 +0100 | |
e57e653a JR |
225 | @@ -158,6 +158,7 @@ |
226 | sema_init(&inode->i_zombie, 1); | |
227 | init_rwsem(&inode->i_alloc_sem); | |
228 | spin_lock_init(&inode->i_data.i_shared_lock); | |
229 | + i_size_ordered_init(inode); | |
230 | } | |
231 | ||
232 | static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) | |
51560e02 AM |
233 | diff -urN linux-2.4.22.org/fs/reiserfs/dir.c linux-2.4.22/fs/reiserfs/dir.c |
234 | --- linux-2.4.22.org/fs/reiserfs/dir.c 2003-08-25 13:44:43.000000000 +0200 | |
235 | +++ linux-2.4.22/fs/reiserfs/dir.c 2003-11-21 15:26:23.000000000 +0100 | |
e57e653a JR |
236 | @@ -110,6 +110,15 @@ |
237 | /* too big to send back to VFS */ | |
238 | continue ; | |
239 | } | |
240 | + | |
241 | + /* Ignore the .reiserfs_priv entry */ | |
242 | + if (reiserfs_xattrs (inode->i_sb) && | |
243 | + !old_format_only(inode->i_sb) && | |
244 | + inode->i_sb->u.reiserfs_sb.priv_root && | |
245 | + inode->i_sb->u.reiserfs_sb.priv_root->d_inode && | |
246 | + deh_objectid (deh) == le32_to_cpu (INODE_PKEY(inode->i_sb->u.reiserfs_sb.priv_root->d_inode)->k_objectid)) | |
247 | + continue; | |
248 | + | |
249 | d_off = deh_offset (deh); | |
250 | filp->f_pos = d_off ; | |
251 | d_ino = deh_objectid (deh); | |
51560e02 AM |
252 | diff -urN linux-2.4.22.org/fs/reiserfs/file.c linux-2.4.22/fs/reiserfs/file.c |
253 | --- linux-2.4.22.org/fs/reiserfs/file.c 2003-11-21 15:14:23.000000000 +0100 | |
254 | +++ linux-2.4.22/fs/reiserfs/file.c 2003-11-21 15:26:23.000000000 +0100 | |
e57e653a JR |
255 | @@ -5,6 +5,8 @@ |
256 | ||
257 | #include <linux/sched.h> | |
258 | #include <linux/reiserfs_fs.h> | |
259 | +#include <linux/reiserfs_acl.h> | |
260 | +#include <linux/reiserfs_xattr.h> | |
261 | #include <linux/smp_lock.h> | |
262 | #include <linux/quotaops.h> | |
263 | ||
264 | @@ -90,61 +92,6 @@ | |
265 | return ( n_err < 0 ) ? -EIO : 0; | |
266 | } | |
267 | ||
268 | -static int reiserfs_setattr(struct dentry *dentry, struct iattr *attr) { | |
269 | - struct inode *inode = dentry->d_inode ; | |
270 | - int error ; | |
271 | - unsigned int ia_valid = attr->ia_valid ; | |
272 | - | |
273 | - if (ia_valid & ATTR_SIZE) { | |
274 | - /* version 2 items will be caught by the s_maxbytes check | |
275 | - ** done for us in vmtruncate | |
276 | - */ | |
277 | - if (get_inode_item_key_version(inode) == KEY_FORMAT_3_5 && | |
278 | - attr->ia_size > MAX_NON_LFS) | |
279 | - return -EFBIG ; | |
280 | - | |
281 | - /* During a truncate, we have to make sure the new i_size is in | |
282 | - ** the transaction before we start dropping updates to data logged | |
283 | - ** or ordered write data pages. | |
284 | - */ | |
285 | - if (attr->ia_size < inode->i_size && reiserfs_file_data_log(inode)) { | |
286 | - struct reiserfs_transaction_handle th ; | |
287 | - journal_begin(&th, inode->i_sb, 1) ; | |
288 | - reiserfs_update_sd_size(&th, inode, attr->ia_size) ; | |
289 | - journal_end(&th, inode->i_sb, 1) ; | |
290 | - /* fill in hole pointers in the expanding truncate case. */ | |
291 | - } else if (attr->ia_size > inode->i_size) { | |
292 | - error = generic_cont_expand(inode, attr->ia_size) ; | |
293 | - if (inode->u.reiserfs_i.i_prealloc_count > 0) { | |
294 | - struct reiserfs_transaction_handle th ; | |
295 | - /* we're changing at most 2 bitmaps, inode + super */ | |
296 | - journal_begin(&th, inode->i_sb, 4) ; | |
297 | - reiserfs_discard_prealloc (&th, inode); | |
298 | - journal_end(&th, inode->i_sb, 4) ; | |
299 | - } | |
300 | - if (error) | |
301 | - return error ; | |
302 | - } | |
303 | - } | |
304 | - | |
305 | - if ((((attr->ia_valid & ATTR_UID) && (attr->ia_uid & ~0xffff)) || | |
306 | - ((attr->ia_valid & ATTR_GID) && (attr->ia_gid & ~0xffff))) && | |
307 | - (get_inode_sd_version (inode) == STAT_DATA_V1)) | |
308 | - /* stat data of format v3.5 has 16 bit uid and gid */ | |
309 | - return -EINVAL; | |
310 | - | |
311 | - error = inode_change_ok(inode, attr) ; | |
312 | - if (!error) { | |
313 | - if ((ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) || | |
314 | - (ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid)) | |
315 | - error = DQUOT_TRANSFER(inode, attr) ? -EDQUOT : 0; | |
316 | - | |
317 | - if (!error) | |
318 | - error = inode_setattr(inode, attr) ; | |
319 | - } | |
320 | - return error ; | |
321 | -} | |
322 | - | |
323 | static ssize_t | |
324 | reiserfs_file_write(struct file *f, const char *b, size_t count, loff_t *ppos) | |
325 | { | |
326 | @@ -173,6 +120,15 @@ | |
327 | struct inode_operations reiserfs_file_inode_operations = { | |
328 | truncate: reiserfs_vfs_truncate_file, | |
329 | setattr: reiserfs_setattr, | |
330 | + setxattr: reiserfs_setxattr, | |
331 | + getxattr: reiserfs_getxattr, | |
332 | + listxattr: reiserfs_listxattr, | |
333 | + removexattr: reiserfs_removexattr, | |
334 | + /* | |
335 | + set_posix_acl: reiserfs_set_acl, | |
336 | + get_posix_acl: reiserfs_get_acl, | |
337 | + */ | |
338 | + permission: reiserfs_permission, | |
339 | }; | |
340 | ||
341 | ||
51560e02 AM |
342 | diff -urN linux-2.4.22.org/fs/reiserfs/inode.c linux-2.4.22/fs/reiserfs/inode.c |
343 | --- linux-2.4.22.org/fs/reiserfs/inode.c 2003-11-21 15:14:23.000000000 +0100 | |
344 | +++ linux-2.4.22/fs/reiserfs/inode.c 2003-11-21 15:26:23.000000000 +0100 | |
e57e653a JR |
345 | @@ -6,6 +6,8 @@ |
346 | #include <linux/sched.h> | |
347 | #include <linux/fs.h> | |
348 | #include <linux/reiserfs_fs.h> | |
349 | +#include <linux/reiserfs_acl.h> | |
350 | +#include <linux/reiserfs_xattr.h> | |
351 | #include <linux/locks.h> | |
352 | #include <linux/smp_lock.h> | |
353 | #include <linux/quotaops.h> | |
354 | @@ -42,6 +44,8 @@ | |
355 | if (INODE_PKEY(inode)->k_objectid != 0) { /* also handles bad_inode case */ | |
356 | down (&inode->i_sem); | |
357 | ||
358 | + reiserfs_delete_xattrs (inode); | |
359 | + | |
360 | journal_begin(&th, inode->i_sb, jbegin_count) ; | |
361 | reiserfs_update_inode_transaction(inode) ; | |
362 | windex = push_journal_writer("delete_inode") ; | |
363 | @@ -351,10 +355,10 @@ | |
364 | ** correct, and when direct item padding results in a few | |
365 | ** extra bytes at the end of the direct item | |
366 | */ | |
367 | - if ((le_ih_k_offset(ih) + path.pos_in_item) > inode->i_size) | |
368 | + if ((le_ih_k_offset(ih) + path.pos_in_item) > i_size_read(inode)) | |
369 | break ; | |
370 | - if ((le_ih_k_offset(ih) - 1 + ih_item_len(ih)) > inode->i_size) { | |
371 | - chars = inode->i_size - (le_ih_k_offset(ih) - 1) - path.pos_in_item; | |
372 | + if ((le_ih_k_offset(ih) - 1 + ih_item_len(ih)) > i_size_read(inode)) { | |
373 | + chars = i_size_read(inode) - (le_ih_k_offset(ih) - 1) - path.pos_in_item; | |
374 | done = 1 ; | |
375 | } else { | |
376 | chars = ih_item_len(ih) - path.pos_in_item; | |
377 | @@ -645,7 +649,7 @@ | |
378 | ** running. So, if we are nesting into someone else, we have to | |
379 | ** make sure and bump the refcount | |
380 | */ | |
381 | - if ((new_offset + inode->i_sb->s_blocksize - 1) > inode->i_size) { | |
382 | + if ((new_offset + inode->i_sb->s_blocksize - 1) > i_size_read(inode)) { | |
383 | th = reiserfs_persistent_transaction(inode->i_sb, jbegin_count) ; | |
384 | if (IS_ERR(th)) { | |
385 | retval = PTR_ERR(th) ; | |
386 | @@ -1022,7 +1026,7 @@ | |
387 | ** tail, we add 4 bytes to pretend there really is an unformatted | |
388 | ** node pointer | |
389 | */ | |
390 | - bytes = ((inode->i_size + (blocksize-1)) >> inode->i_sb->s_blocksize_bits) * UNFM_P_SIZE + sd_size; | |
391 | + bytes = ((i_size_read(inode) + (blocksize-1)) >> inode->i_sb->s_blocksize_bits) * UNFM_P_SIZE + sd_size; | |
392 | return bytes ; | |
393 | } | |
394 | ||
395 | @@ -1030,7 +1034,7 @@ | |
396 | int sd_size) | |
397 | { | |
398 | if (S_ISLNK(inode->i_mode) || S_ISDIR(inode->i_mode)) { | |
399 | - return inode->i_size + (loff_t)(real_space_diff(inode, sd_size)) ; | |
400 | + return i_size_read(inode) + (loff_t)(real_space_diff(inode, sd_size)) ; | |
401 | } | |
402 | return ((loff_t)real_space_diff(inode, sd_size)) + (((loff_t)blocks) << 9); | |
403 | } | |
404 | @@ -1165,7 +1169,7 @@ | |
405 | inode->i_op = &reiserfs_dir_inode_operations; | |
406 | inode->i_fop = &reiserfs_dir_operations; | |
407 | } else if (S_ISLNK (inode->i_mode)) { | |
408 | - inode->i_op = &page_symlink_inode_operations; | |
409 | + inode->i_op = &reiserfs_symlink_inode_operations; | |
410 | inode->i_mapping->a_ops = &reiserfs_address_space_operations; | |
411 | } else { | |
412 | inode->i_blocks = 0; | |
413 | @@ -1843,6 +1847,17 @@ | |
414 | goto out_inserted_sd; | |
415 | } | |
416 | ||
417 | + if (reiserfs_posixacl (inode->i_sb)) { | |
418 | + retval = reiserfs_inherit_default_acl (dir, dentry, inode); | |
419 | + if (retval) { | |
420 | + err = retval; | |
421 | + reiserfs_check_path(&path_to_key) ; | |
422 | + goto out_inserted_sd; | |
423 | + } | |
424 | + } else if (inode->i_sb->s_flags & MS_POSIXACL) { | |
425 | + reiserfs_warning (inode->i_sb, "ACLs aren't enabled in the fs, but vfs thinks they are!\n"); | |
426 | + } | |
427 | + | |
428 | insert_inode_hash (inode); | |
429 | reiserfs_update_sd(th, inode) ; | |
430 | reiserfs_check_path(&path_to_key) ; | |
431 | @@ -1885,6 +1900,8 @@ | |
432 | ||
433 | /* we want the page with the last byte in the file, | |
434 | ** not the page that will hold the next byte for appending | |
435 | + ** | |
436 | + ** we are called with i_sem held, so we don't need i_size_read() | |
437 | */ | |
438 | unsigned long index = (p_s_inode->i_size-1) >> PAGE_CACHE_SHIFT ; | |
439 | unsigned long pos = 0 ; | |
440 | @@ -2132,7 +2149,7 @@ | |
441 | ||
442 | /* are there still bytes left? */ | |
443 | if (bytes_copied < bh_result->b_size && | |
444 | - (byte_offset + bytes_copied) < inode->i_size) { | |
445 | + (byte_offset + bytes_copied) < i_size_read(inode)) { | |
446 | set_cpu_key_k_offset(&key, cpu_key_k_offset(&key) + copy_size) ; | |
447 | goto research ; | |
448 | } | |
449 | @@ -2228,7 +2245,7 @@ | |
450 | ||
451 | static int reiserfs_write_full_page(struct page *page) { | |
452 | struct inode *inode = page->mapping->host ; | |
453 | - loff_t size = inode->i_size; | |
454 | + loff_t size = i_size_read(inode); | |
455 | unsigned long end_index = size >> PAGE_CACHE_SHIFT ; | |
456 | unsigned last_offset = PAGE_CACHE_SIZE; | |
457 | int error = 0; | |
458 | @@ -2482,6 +2499,7 @@ | |
459 | th.t_flags = 0 ; | |
460 | ret = __commit_write(&th, inode, page, from, to, &need_balance) ; | |
461 | ||
462 | + /* i_sem is held, i_size_read is not required */ | |
463 | if (pos > inode->i_size) { | |
464 | lock_kernel(); | |
465 | /* If the file have grown beyond the border where it | |
466 | @@ -2495,7 +2513,7 @@ | |
467 | journal_begin(&th, inode->i_sb, 1) ; | |
468 | } | |
469 | reiserfs_update_inode_transaction(inode) ; | |
470 | - inode->i_size = pos ; | |
471 | + i_size_write(inode, pos); | |
472 | reiserfs_update_sd(&th, inode) ; | |
473 | journal_end(&th, th.t_super, th.t_blocks_allocated) ; | |
474 | unlock_kernel() ; | |
475 | @@ -2685,6 +2703,79 @@ | |
476 | reiserfs_get_block_direct_io) ; | |
477 | } | |
478 | ||
479 | +int reiserfs_setattr(struct dentry *dentry, struct iattr *attr) { | |
480 | + struct inode *inode = dentry->d_inode ; | |
481 | + int error ; | |
482 | + unsigned int ia_valid = attr->ia_valid ; | |
483 | + | |
484 | + if (ia_valid & ATTR_SIZE) { | |
485 | + /* version 2 items will be caught by the s_maxbytes check | |
486 | + ** done for us in vmtruncate | |
487 | + */ | |
488 | + if (get_inode_item_key_version(inode) == KEY_FORMAT_3_5 && | |
489 | + attr->ia_size > MAX_NON_LFS) | |
490 | + return -EFBIG ; | |
491 | + | |
492 | + /* During a truncate, we have to make sure the new i_size is in | |
493 | + ** the transaction before we start dropping updates to data logged | |
494 | + ** or ordered write data pages. | |
495 | + */ | |
496 | + if (attr->ia_size < i_size_read(inode) && reiserfs_file_data_log(inode)) { | |
497 | + struct reiserfs_transaction_handle th ; | |
498 | + journal_begin(&th, inode->i_sb, 1) ; | |
499 | + reiserfs_update_sd_size(&th, inode, attr->ia_size) ; | |
500 | + journal_end(&th, inode->i_sb, 1) ; | |
501 | + /* fill in hole pointers in the expanding truncate case. */ | |
502 | + } else if (attr->ia_size > i_size_read(inode)) { | |
503 | + error = generic_cont_expand(inode, attr->ia_size) ; | |
504 | + if (inode->u.reiserfs_i.i_prealloc_count > 0) { | |
505 | + struct reiserfs_transaction_handle th ; | |
506 | + /* we're changing at most 2 bitmaps, inode + super */ | |
507 | + journal_begin(&th, inode->i_sb, 4) ; | |
508 | + reiserfs_discard_prealloc (&th, inode); | |
509 | + journal_end(&th, inode->i_sb, 4) ; | |
510 | + } | |
511 | + if (error) | |
512 | + return error ; | |
513 | + } | |
514 | + } | |
515 | + | |
516 | + if ((((attr->ia_valid & ATTR_UID) && (attr->ia_uid & ~0xffff)) || | |
517 | + ((attr->ia_valid & ATTR_GID) && (attr->ia_gid & ~0xffff))) && | |
518 | + (get_inode_sd_version (inode) == STAT_DATA_V1)) | |
519 | + /* stat data of format v3.5 has 16 bit uid and gid */ | |
520 | + return -EINVAL; | |
521 | + | |
522 | + error = inode_change_ok(inode, attr) ; | |
523 | + if (!error) { | |
524 | + if ((ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) || | |
525 | + (ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid)) { | |
526 | + if (!(attr->ia_valid & ATTR_SIZE)) | |
527 | + down (&inode->i_sem); | |
528 | + error = reiserfs_chown_xattrs (inode, attr); | |
529 | + if (!(attr->ia_valid & ATTR_SIZE)) | |
530 | + up (&inode->i_sem); | |
531 | + | |
532 | + if (!error) | |
533 | + error = DQUOT_TRANSFER(inode, attr) ? -EDQUOT : 0; | |
534 | + } | |
535 | + if (!error) | |
536 | + error = inode_setattr(inode, attr) ; | |
537 | + } | |
538 | + | |
539 | + if (!error && reiserfs_posixacl (inode->i_sb) && !S_ISLNK(inode->i_mode)) { | |
540 | + if (attr->ia_valid & ATTR_MODE) { | |
541 | + if (!(attr->ia_valid & ATTR_SIZE)) | |
542 | + down (&inode->i_sem); | |
543 | + error = reiserfs_acl_chmod (inode); | |
544 | + if (!(attr->ia_valid & ATTR_SIZE)) | |
545 | + up (&inode->i_sem); | |
546 | + } | |
547 | + } | |
548 | + | |
549 | + return error ; | |
550 | +} | |
551 | + | |
552 | struct address_space_operations reiserfs_address_space_operations = { | |
553 | writepage: reiserfs_writepage, | |
554 | readpage: reiserfs_readpage, | |
51560e02 AM |
555 | diff -urN linux-2.4.22.org/fs/reiserfs/ioctl.c linux-2.4.22/fs/reiserfs/ioctl.c |
556 | --- linux-2.4.22.org/fs/reiserfs/ioctl.c 2003-11-21 15:14:23.000000000 +0100 | |
557 | +++ linux-2.4.22/fs/reiserfs/ioctl.c 2003-11-21 15:26:23.000000000 +0100 | |
e57e653a JR |
558 | @@ -110,7 +110,7 @@ |
559 | unsigned long write_from ; | |
560 | unsigned long blocksize = inode->i_sb->s_blocksize ; | |
561 | ||
562 | - if (inode->i_size == 0) { | |
563 | + if (i_size_read(inode) == 0) { | |
564 | inode->u.reiserfs_i.i_flags |= i_nopack_mask; | |
565 | return 0 ; | |
566 | } | |
51560e02 AM |
567 | diff -urN linux-2.4.22.org/fs/reiserfs/Makefile linux-2.4.22/fs/reiserfs/Makefile |
568 | --- linux-2.4.22.org/fs/reiserfs/Makefile 2003-11-21 15:14:23.000000000 +0100 | |
569 | +++ linux-2.4.22/fs/reiserfs/Makefile 2003-11-21 15:26:23.000000000 +0100 | |
e57e653a JR |
570 | @@ -12,6 +12,11 @@ |
571 | obj-y := bitmap.o do_balan.o namei.o inode.o file.o dir.o fix_node.o super.o prints.o objectid.o \ | |
572 | lbalance.o ibalance.o stree.o hashes.o buffer2.o tail_conversion.o journal.o resize.o item_ops.o ioctl.o procfs.o | |
573 | ||
574 | +obj-$(CONFIG_REISERFS_FS_XATTR) += xattr.o | |
575 | +obj-$(CONFIG_REISERFS_FS_XATTR_USER) += xattr_user.o | |
576 | +obj-$(CONFIG_REISERFS_FS_XATTR_TRUSTED) += xattr_trusted.o | |
577 | +obj-$(CONFIG_REISERFS_FS_POSIX_ACL) += xattr_acl.o | |
578 | + | |
579 | obj-m := $(O_TARGET) | |
580 | ||
581 | # gcc -O2 (the kernel default) is overaggressive on ppc32 when many inline | |
51560e02 AM |
582 | diff -urN linux-2.4.22.org/fs/reiserfs/namei.c linux-2.4.22/fs/reiserfs/namei.c |
583 | --- linux-2.4.22.org/fs/reiserfs/namei.c 2003-11-21 15:14:23.000000000 +0100 | |
584 | +++ linux-2.4.22/fs/reiserfs/namei.c 2003-11-21 15:26:23.000000000 +0100 | |
e57e653a JR |
585 | @@ -6,6 +6,8 @@ |
586 | #include <linux/sched.h> | |
587 | #include <linux/bitops.h> | |
588 | #include <linux/reiserfs_fs.h> | |
589 | +#include <linux/reiserfs_acl.h> | |
590 | +#include <linux/reiserfs_xattr.h> | |
591 | #include <linux/smp_lock.h> | |
592 | #include <linux/quotaops.h> | |
593 | ||
594 | @@ -271,7 +273,7 @@ | |
595 | ||
596 | // may return NAME_FOUND, NAME_FOUND_INVISIBLE, NAME_NOT_FOUND | |
597 | // FIXME: should add something like IOERROR | |
598 | -static int reiserfs_find_entry (struct inode * dir, const char * name, int namelen, | |
599 | +int reiserfs_find_entry (struct inode * dir, const char * name, int namelen, | |
600 | struct path * path_to_entry, struct reiserfs_dir_entry * de) | |
601 | { | |
602 | struct cpu_key key_to_search; | |
603 | @@ -324,10 +326,21 @@ | |
604 | retval = reiserfs_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &path_to_entry, &de); | |
605 | pathrelse (&path_to_entry); | |
606 | if (retval == NAME_FOUND) { | |
607 | + /* Hide the .reiserfs_priv dir */ | |
608 | + if (reiserfs_xattrs (dir->i_sb) && | |
609 | + !old_format_only(dir->i_sb) && | |
610 | + dir->i_sb->u.reiserfs_sb.priv_root && | |
611 | + dir->i_sb->u.reiserfs_sb.priv_root->d_inode && | |
612 | + de.de_objectid == le32_to_cpu (INODE_PKEY(dir->i_sb->u.reiserfs_sb.priv_root->d_inode)->k_objectid)) { | |
613 | + return ERR_PTR (-EACCES); | |
614 | + } | |
615 | inode = reiserfs_iget (dir->i_sb, (struct cpu_key *)&(de.de_dir_id)); | |
616 | if (!inode || IS_ERR(inode)) { | |
617 | return ERR_PTR(-EACCES); | |
618 | } | |
619 | + /* Propogate the priv_object flag so we know we're in the priv tree */ | |
620 | + if (is_reiserfs_priv_object (dir)) | |
621 | + inode->u.reiserfs_i.i_flags |= i_priv_object; | |
622 | } | |
623 | if ( retval == IO_ERROR ) { | |
624 | return ERR_PTR(-EIO); | |
625 | @@ -534,6 +547,7 @@ | |
626 | struct inode * inode; | |
627 | int jbegin_count = JOURNAL_PER_BALANCE_CNT * 2 ; | |
628 | struct reiserfs_transaction_handle th ; | |
629 | + int locked; | |
630 | ||
631 | if (!(inode = new_inode(dir->i_sb))) { | |
632 | return -ENOMEM ; | |
633 | @@ -542,8 +556,16 @@ | |
634 | if (retval) | |
635 | return retval ; | |
636 | ||
637 | + locked = reiserfs_cache_default_acl (dir); | |
638 | + if (locked) | |
639 | + reiserfs_write_lock_xattrs (inode->i_sb); | |
640 | + | |
641 | journal_begin(&th, dir->i_sb, jbegin_count) ; | |
642 | retval = reiserfs_new_inode (&th, dir, mode, 0, 0/*i_size*/, dentry, inode); | |
643 | + | |
644 | + if (locked) | |
645 | + reiserfs_write_unlock_xattrs (inode->i_sb); | |
646 | + | |
647 | if (retval) { | |
648 | goto out_failed ; | |
649 | } | |
650 | @@ -579,6 +601,7 @@ | |
651 | struct inode * inode; | |
652 | struct reiserfs_transaction_handle th ; | |
653 | int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3; | |
654 | + int locked; | |
655 | ||
656 | if (!(inode = new_inode(dir->i_sb))) { | |
657 | return -ENOMEM ; | |
658 | @@ -587,9 +610,17 @@ | |
659 | if (retval) | |
660 | return retval ; | |
661 | ||
662 | + locked = reiserfs_cache_default_acl (dir); | |
663 | + if (locked) | |
664 | + reiserfs_write_lock_xattrs (inode->i_sb); | |
665 | + | |
666 | journal_begin(&th, dir->i_sb, jbegin_count) ; | |
667 | ||
668 | retval = reiserfs_new_inode(&th, dir, mode, 0, 0/*i_size*/, dentry, inode); | |
669 | + | |
670 | + if (locked) | |
671 | + reiserfs_write_unlock_xattrs (inode->i_sb); | |
672 | + | |
673 | if (retval) { | |
674 | goto out_failed; | |
675 | } | |
676 | @@ -627,6 +658,7 @@ | |
677 | struct inode * inode; | |
678 | struct reiserfs_transaction_handle th ; | |
679 | int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3; | |
680 | + int locked; | |
681 | ||
682 | mode = S_IFDIR | mode; | |
683 | if (!(inode = new_inode(dir->i_sb))) { | |
684 | @@ -636,6 +668,10 @@ | |
685 | if (retval) | |
686 | return retval ; | |
687 | ||
688 | + locked = reiserfs_cache_default_acl (dir); | |
689 | + if (locked) | |
690 | + reiserfs_write_lock_xattrs (inode->i_sb); | |
691 | + | |
692 | journal_begin(&th, dir->i_sb, jbegin_count) ; | |
693 | ||
694 | /* inc the link count now, so another writer doesn't overflow it while | |
695 | @@ -651,6 +687,9 @@ | |
696 | old_format_only (dir->i_sb) ? | |
697 | EMPTY_DIR_SIZE_V1 : EMPTY_DIR_SIZE, | |
698 | dentry, inode) ; | |
699 | + if (locked) | |
700 | + reiserfs_write_unlock_xattrs (inode->i_sb); | |
701 | + | |
702 | if (retval) { | |
703 | dir->i_nlink-- ; | |
704 | goto out_failed ; | |
705 | @@ -871,7 +910,6 @@ | |
706 | struct reiserfs_transaction_handle th ; | |
707 | int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3; | |
708 | ||
709 | - | |
710 | if (!(inode = new_inode(parent_dir->i_sb))) { | |
711 | return -ENOMEM ; | |
712 | } | |
713 | @@ -896,11 +934,14 @@ | |
714 | memcpy (name, symname, strlen (symname)); | |
715 | padd_item (name, item_len, strlen (symname)); | |
716 | ||
717 | + /* We would inherit the default ACL here, but symlinks don't get ACLs */ | |
718 | + | |
719 | journal_begin(&th, parent_dir->i_sb, jbegin_count) ; | |
720 | ||
721 | retval = reiserfs_new_inode(&th, parent_dir, mode, name, | |
722 | strlen(symname), dentry, inode) ; | |
723 | reiserfs_kfree (name, item_len, parent_dir->i_sb); | |
724 | + | |
725 | if (retval) { | |
726 | goto out_failed ; | |
727 | } | |
728 | @@ -908,7 +949,7 @@ | |
729 | reiserfs_update_inode_transaction(inode) ; | |
730 | reiserfs_update_inode_transaction(parent_dir) ; | |
731 | ||
732 | - inode->i_op = &page_symlink_inode_operations; | |
733 | + inode->i_op = &reiserfs_symlink_inode_operations; | |
734 | inode->i_mapping->a_ops = &reiserfs_address_space_operations; | |
735 | ||
736 | // must be sure this inode is written with this transaction | |
737 | @@ -934,10 +975,9 @@ | |
738 | } | |
739 | ||
740 | ||
741 | -static int reiserfs_link (struct dentry * old_dentry, struct inode * dir, struct dentry * dentry) | |
742 | +int __reiserfs_link (struct inode * inode, struct inode * dir, struct dentry * dentry) | |
743 | { | |
744 | int retval; | |
745 | - struct inode *inode = old_dentry->d_inode; | |
746 | int windex ; | |
747 | struct reiserfs_transaction_handle th ; | |
748 | int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3; | |
749 | @@ -986,6 +1026,10 @@ | |
750 | return 0; | |
751 | } | |
752 | ||
753 | +static int reiserfs_link (struct dentry * old_dentry, struct inode * dir, struct dentry * dentry) | |
754 | +{ | |
755 | + return __reiserfs_link (old_dentry->d_inode, dir, dentry); | |
756 | +} | |
757 | ||
758 | // de contains information pointing to an entry which | |
759 | static int de_still_valid (const char * name, int len, struct reiserfs_dir_entry * de) | |
760 | @@ -1280,5 +1324,33 @@ | |
761 | rmdir: reiserfs_rmdir, | |
762 | mknod: reiserfs_mknod, | |
763 | rename: reiserfs_rename, | |
764 | + setattr: reiserfs_setattr, | |
765 | + setxattr: reiserfs_setxattr, | |
766 | + getxattr: reiserfs_getxattr, | |
767 | + listxattr: reiserfs_listxattr, | |
768 | + removexattr: reiserfs_removexattr, | |
769 | + /* | |
770 | + set_posix_acl: reiserfs_set_acl, | |
771 | + get_posix_acl: reiserfs_get_acl, | |
772 | + */ | |
773 | + permission: reiserfs_permission, | |
774 | }; | |
775 | ||
776 | +/* | |
777 | + * symlink operations.. same as page_symlink_inode_operations, with xattr | |
778 | + * stuff added | |
779 | + */ | |
780 | +struct inode_operations reiserfs_symlink_inode_operations = { | |
781 | + readlink: page_readlink, | |
782 | + follow_link: page_follow_link, | |
783 | + setattr: reiserfs_setattr, | |
784 | + setxattr: reiserfs_setxattr, | |
785 | + getxattr: reiserfs_getxattr, | |
786 | + listxattr: reiserfs_listxattr, | |
787 | + removexattr: reiserfs_removexattr, | |
788 | + /* | |
789 | + set_posix_acl: reiserfs_set_acl, | |
790 | + get_posix_acl: reiserfs_get_acl, | |
791 | + */ | |
792 | + permission: reiserfs_permission, | |
793 | +}; | |
51560e02 AM |
794 | diff -urN linux-2.4.22.org/fs/reiserfs/stree.c linux-2.4.22/fs/reiserfs/stree.c |
795 | --- linux-2.4.22.org/fs/reiserfs/stree.c 2003-11-21 15:14:25.000000000 +0100 | |
796 | +++ linux-2.4.22/fs/reiserfs/stree.c 2003-11-21 15:26:23.000000000 +0100 | |
e57e653a JR |
797 | @@ -1451,7 +1451,7 @@ |
798 | ||
799 | void reiserfs_delete_object (struct reiserfs_transaction_handle *th, struct inode * inode) | |
800 | { | |
801 | - inode->i_size = 0; | |
802 | + i_size_write(inode, 0); | |
803 | ||
804 | /* for directory this deletes item containing "." and ".." */ | |
805 | reiserfs_do_truncate (th, inode, NULL, 0/*no timestamp updates*/); | |
806 | @@ -1483,6 +1483,7 @@ | |
807 | int n_block_size = p_s_sb->s_blocksize; | |
808 | int cut_bytes; | |
809 | ||
810 | + /* i_sem is held, i_size_read not required */ | |
811 | if (n_new_file_size != p_s_inode->i_size) | |
812 | BUG (); | |
813 | ||
51560e02 AM |
814 | diff -urN linux-2.4.22.org/fs/reiserfs/super.c linux-2.4.22/fs/reiserfs/super.c |
815 | --- linux-2.4.22.org/fs/reiserfs/super.c 2003-11-21 15:14:25.000000000 +0100 | |
816 | +++ linux-2.4.22/fs/reiserfs/super.c 2003-11-21 15:26:23.000000000 +0100 | |
e57e653a JR |
817 | @@ -9,6 +9,8 @@ |
818 | #include <linux/vmalloc.h> | |
819 | #include <asm/uaccess.h> | |
820 | #include <linux/reiserfs_fs.h> | |
821 | +#include <linux/reiserfs_acl.h> | |
822 | +#include <linux/reiserfs_xattr.h> | |
823 | #include <linux/smp_lock.h> | |
824 | #include <linux/locks.h> | |
825 | #include <linux/init.h> | |
826 | @@ -354,7 +356,19 @@ | |
827 | { | |
828 | int i; | |
829 | struct reiserfs_transaction_handle th ; | |
830 | + | |
831 | + reiserfs_xattr_cache_clear (s->s_dev); | |
832 | + | |
833 | + if (s->u.reiserfs_sb.xattr_root) { | |
834 | + d_invalidate (s->u.reiserfs_sb.xattr_root); | |
835 | + dput (s->u.reiserfs_sb.xattr_root); | |
836 | + } | |
837 | ||
838 | + if (s->u.reiserfs_sb.priv_root) { | |
839 | + d_invalidate (s->u.reiserfs_sb.priv_root); | |
840 | + dput (s->u.reiserfs_sb.priv_root); | |
841 | + } | |
842 | + | |
843 | /* change file system state to current state if it was mounted with read-write permissions */ | |
844 | if (!(s->s_flags & MS_RDONLY)) { | |
845 | journal_begin(&th, s, 10) ; | |
846 | @@ -419,6 +433,22 @@ | |
847 | unlock_kernel() ; | |
848 | } | |
849 | ||
850 | +static void reiserfs_clear_inode (struct inode *inode) | |
851 | +{ | |
852 | + struct posix_acl *acl; | |
853 | + | |
854 | + acl = inode->u.reiserfs_i.i_acl_access; | |
855 | + if (acl && !IS_ERR (acl)) | |
856 | + posix_acl_release (acl); | |
857 | + inode->u.reiserfs_i.i_acl_access = NULL; | |
858 | + | |
859 | + acl = inode->u.reiserfs_i.i_acl_default; | |
860 | + if (acl && !IS_ERR (acl)) | |
861 | + posix_acl_release (acl); | |
862 | + inode->u.reiserfs_i.i_acl_default = NULL; | |
863 | +} | |
864 | + | |
865 | + | |
866 | struct super_operations reiserfs_sops = | |
867 | { | |
868 | read_inode: reiserfs_read_inode, | |
869 | @@ -426,6 +456,7 @@ | |
870 | write_inode: reiserfs_write_inode, | |
871 | dirty_inode: reiserfs_dirty_inode, | |
872 | delete_inode: reiserfs_delete_inode, | |
873 | + clear_inode: reiserfs_clear_inode, | |
874 | put_super: reiserfs_put_super, | |
875 | write_super: reiserfs_write_super, | |
876 | write_super_lockfs: reiserfs_write_super_lockfs, | |
877 | @@ -639,7 +670,16 @@ | |
878 | {"noattrs", 0, 0, 0, 1<<REISERFS_ATTRS}, | |
879 | {"usrquota", 0, 0, 0, 0}, | |
880 | {"grpquota", 0, 0, 0, 0}, | |
881 | - | |
882 | +#ifdef CONFIG_REISERFS_FS_XATTR | |
883 | +# ifdef CONFIG_REISERFS_FS_XATTR_USER | |
884 | + {"user_xattr", 0, 0, 1<<REISERFS_XATTRS_USER}, | |
885 | + {"nouser_xattr", 0, 0, 1<<REISERFS_NO_XATTRS_USER}, | |
886 | +# endif | |
887 | +# ifdef CONFIG_REISERFS_FS_POSIX_ACL | |
888 | + {"acl", 0, 0, 1<<REISERFS_POSIXACL}, | |
889 | + {"noacl", 0, 0, 1<<REISERFS_NO_POSIXACL}, | |
890 | +# endif | |
891 | +#endif | |
892 | {NULL, 0, 0, 0, 0} | |
893 | }; | |
894 | ||
895 | @@ -757,6 +797,10 @@ | |
896 | safe_mask |= 1 << REISERFS_HASHED_RELOCATION; | |
897 | safe_mask |= 1 << REISERFS_TEST4; | |
898 | safe_mask |= 1 << REISERFS_ATTRS; | |
899 | + safe_mask |= 1 << REISERFS_XATTRS_USER; | |
900 | + safe_mask |= 1 << REISERFS_NO_XATTRS_USER; | |
901 | + safe_mask |= 1 << REISERFS_POSIXACL; | |
902 | + safe_mask |= 1 << REISERFS_NO_POSIXACL; | |
903 | ||
904 | /* Update the bitmask, taking care to keep | |
905 | * the bits we're not allowed to change here */ | |
906 | @@ -771,6 +815,7 @@ | |
907 | } | |
908 | ||
909 | if (*mount_flags & MS_RDONLY) { | |
910 | + reiserfs_xattr_init (s, *mount_flags); | |
911 | /* remount read-only */ | |
912 | if (s->s_flags & MS_RDONLY) | |
913 | /* it is read-only already */ | |
914 | @@ -789,6 +834,7 @@ | |
915 | } else { | |
916 | /* remount read-write */ | |
917 | if (!(s->s_flags & MS_RDONLY)) { | |
918 | + reiserfs_xattr_init (s, *mount_flags); | |
919 | handle_data_mode(s, mount_options); | |
920 | return 0; /* We are read-write already */ | |
921 | } | |
922 | @@ -812,6 +858,7 @@ | |
923 | if (!( *mount_flags & MS_RDONLY ) ) { | |
924 | finish_unfinished( s ); | |
925 | handle_data_mode(s, mount_options); | |
926 | + reiserfs_xattr_init (s, *mount_flags); | |
927 | } | |
928 | return 0; | |
929 | } | |
930 | @@ -1236,6 +1283,8 @@ | |
931 | s->u.reiserfs_sb.s_alloc_options.preallocmin = 4; | |
932 | /* Preallocate by 8 blocks (9-1) at once */ | |
933 | s->u.reiserfs_sb.s_alloc_options.preallocsize = 9; | |
934 | + /* Initialize the rwsem for xattr dir */ | |
935 | + init_rwsem(&s->u.reiserfs_sb.xattr_dir_sem); | |
936 | ||
937 | if (reiserfs_parse_options (s, (char *) data, &(s->u.reiserfs_sb.s_mount_opt), &blocks) == 0) { | |
938 | return NULL; | |
939 | @@ -1378,11 +1427,23 @@ | |
940 | ||
941 | journal_mark_dirty(&th, s, SB_BUFFER_WITH_SB (s)); | |
942 | journal_end(&th, s, 1) ; | |
943 | - | |
944 | + | |
945 | + if (reiserfs_xattr_init (s, s->s_flags)) { | |
946 | + dput (s->s_root); | |
947 | + s->s_root = NULL; | |
948 | + goto error; | |
949 | + } | |
950 | + | |
951 | /* look for files which were to be removed in previous session */ | |
952 | finish_unfinished (s); | |
953 | ||
954 | s->s_dirt = 0; | |
955 | + } else { | |
956 | + if (reiserfs_xattr_init (s, s->s_flags)) { | |
957 | + dput (s->s_root); | |
958 | + s->s_root = NULL; | |
959 | + goto error; | |
960 | + } | |
961 | } | |
962 | ||
963 | // mark hash in super block: it could be unset. overwrite should be ok | |
964 | @@ -1445,10 +1506,37 @@ | |
965 | reiserfs_proc_info_global_init(); | |
966 | reiserfs_proc_register_global( "version", | |
967 | reiserfs_global_version_in_proc ); | |
968 | + | |
969 | ret = reiserfs_journal_cache_init(); | |
970 | - if (ret) | |
971 | - return ret; | |
972 | - return register_filesystem(&reiserfs_fs_type); | |
973 | + if (ret) goto failed_reiserfs_journal_cache_init; | |
974 | + | |
975 | + ret = reiserfs_xattr_cache_init(); | |
976 | + if (ret) goto failed_xattr_cache_init; | |
977 | + | |
978 | + ret = reiserfs_xattr_user_init(); | |
979 | + if (ret) goto failed_xattr_user_init; | |
980 | + | |
981 | + ret = reiserfs_xattr_trusted_init(); | |
982 | + if (ret) goto failed_xattr_trusted_init; | |
983 | + | |
984 | + ret = reiserfs_xattr_posix_acl_init(); | |
985 | + if (ret) goto failed_xattr_posix_acl_init; | |
986 | + | |
987 | + return register_filesystem(&reiserfs_fs_type); | |
988 | + | |
989 | +failed_xattr_posix_acl_init: | |
990 | + reiserfs_xattr_trusted_exit(); | |
991 | +failed_xattr_trusted_init: | |
992 | + reiserfs_xattr_user_exit(); | |
993 | +failed_xattr_user_init: | |
994 | + reiserfs_xattr_cache_exit(); | |
995 | +failed_xattr_cache_init: | |
996 | + /* reiserfs_journal_cache_exit(); */ | |
997 | +failed_reiserfs_journal_cache_init: | |
998 | + | |
999 | + reiserfs_proc_unregister_global( "version" ); | |
1000 | + reiserfs_proc_info_global_done(); | |
1001 | + return ret; | |
1002 | } | |
1003 | ||
1004 | MODULE_DESCRIPTION("ReiserFS journaled filesystem"); | |
1005 | @@ -1457,6 +1545,10 @@ | |
1006 | ||
1007 | static void __exit exit_reiserfs_fs(void) | |
1008 | { | |
1009 | + reiserfs_xattr_posix_acl_exit (); | |
1010 | + reiserfs_xattr_trusted_exit (); | |
1011 | + reiserfs_xattr_user_exit (); | |
1012 | + reiserfs_xattr_cache_exit (); | |
1013 | reiserfs_proc_unregister_global( "version" ); | |
1014 | reiserfs_proc_info_global_done(); | |
1015 | unregister_filesystem(&reiserfs_fs_type); | |
51560e02 AM |
1016 | diff -urN linux-2.4.22.org/fs/reiserfs/xattr_acl.c linux-2.4.22/fs/reiserfs/xattr_acl.c |
1017 | --- linux-2.4.22.org/fs/reiserfs/xattr_acl.c 1970-01-01 01:00:00.000000000 +0100 | |
1018 | +++ linux-2.4.22/fs/reiserfs/xattr_acl.c 2003-11-21 15:26:23.000000000 +0100 | |
e57e653a JR |
1019 | @@ -0,0 +1,653 @@ |
1020 | +#include <linux/posix_acl.h> | |
1021 | +#include <linux/reiserfs_fs.h> | |
1022 | +#include <linux/errno.h> | |
1023 | +#include <linux/fs.h> | |
1024 | +#include <linux/pagemap.h> | |
1025 | +#include <linux/xattr.h> | |
1026 | +#include <linux/xattr_acl.h> | |
1027 | +#include <linux/reiserfs_xattr.h> | |
1028 | +#include <linux/reiserfs_acl.h> | |
1029 | +#include <asm/uaccess.h> | |
1030 | + | |
1031 | +static int | |
1032 | +xattr_set_acl(struct inode *inode, int type, const void *value, size_t size) | |
1033 | +{ | |
1034 | + struct posix_acl *acl; | |
1035 | + int error; | |
1036 | + | |
1037 | + if (!reiserfs_posixacl(inode->i_sb)) | |
1038 | + return -EOPNOTSUPP; | |
1039 | + if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER)) | |
1040 | + return -EPERM; | |
1041 | + | |
1042 | + if (value) { | |
1043 | + acl = posix_acl_from_xattr(value, size); | |
1044 | + if (IS_ERR(acl)) { | |
1045 | + return PTR_ERR(acl); | |
1046 | + } else if (acl) { | |
1047 | + error = posix_acl_valid(acl); | |
1048 | + if (error) | |
1049 | + goto release_and_out; | |
1050 | + } | |
1051 | + } else | |
1052 | + acl = NULL; | |
1053 | + | |
1054 | + error = reiserfs_set_acl (inode, type, acl); | |
1055 | + | |
1056 | +release_and_out: | |
1057 | + posix_acl_release(acl); | |
1058 | + return error; | |
1059 | +} | |
1060 | + | |
1061 | + | |
1062 | +static int | |
1063 | +xattr_get_acl(struct inode *inode, int type, void *buffer, size_t size) | |
1064 | +{ | |
1065 | + struct posix_acl *acl; | |
1066 | + int error; | |
1067 | + | |
1068 | + if (!reiserfs_posixacl(inode->i_sb)) | |
1069 | + return -EOPNOTSUPP; | |
1070 | + | |
1071 | + acl = reiserfs_get_acl (inode, type); | |
1072 | + if (IS_ERR(acl)) | |
1073 | + return PTR_ERR(acl); | |
1074 | + if (acl == NULL) | |
1075 | + return -ENODATA; | |
1076 | + error = posix_acl_to_xattr(acl, buffer, size); | |
1077 | + posix_acl_release(acl); | |
1078 | + | |
1079 | + return error; | |
1080 | +} | |
1081 | + | |
1082 | + | |
1083 | +/* | |
1084 | + * Convert from filesystem to in-memory representation. | |
1085 | + */ | |
1086 | +static struct posix_acl * | |
1087 | +posix_acl_from_disk(const void *value, size_t size) | |
1088 | +{ | |
1089 | + const char *end = (char *)value + size; | |
1090 | + int n, count; | |
1091 | + struct posix_acl *acl; | |
1092 | + | |
1093 | + if (!value) | |
1094 | + return NULL; | |
1095 | + if (size < sizeof(reiserfs_acl_header)) | |
1096 | + return ERR_PTR(-EINVAL); | |
1097 | + if (((reiserfs_acl_header *)value)->a_version != | |
1098 | + cpu_to_le32(REISERFS_ACL_VERSION)) | |
1099 | + return ERR_PTR(-EINVAL); | |
1100 | + value = (char *)value + sizeof(reiserfs_acl_header); | |
1101 | + count = reiserfs_acl_count(size); | |
1102 | + if (count < 0) | |
1103 | + return ERR_PTR(-EINVAL); | |
1104 | + if (count == 0) | |
1105 | + return NULL; | |
1106 | + acl = posix_acl_alloc(count, GFP_NOFS); | |
1107 | + if (!acl) | |
1108 | + return ERR_PTR(-ENOMEM); | |
1109 | + for (n=0; n < count; n++) { | |
1110 | + reiserfs_acl_entry *entry = | |
1111 | + (reiserfs_acl_entry *)value; | |
1112 | + if ((char *)value + sizeof(reiserfs_acl_entry_short) > end) | |
1113 | + goto fail; | |
1114 | + acl->a_entries[n].e_tag = le16_to_cpu(entry->e_tag); | |
1115 | + acl->a_entries[n].e_perm = le16_to_cpu(entry->e_perm); | |
1116 | + switch(acl->a_entries[n].e_tag) { | |
1117 | + case ACL_USER_OBJ: | |
1118 | + case ACL_GROUP_OBJ: | |
1119 | + case ACL_MASK: | |
1120 | + case ACL_OTHER: | |
1121 | + value = (char *)value + | |
1122 | + sizeof(reiserfs_acl_entry_short); | |
1123 | + acl->a_entries[n].e_id = ACL_UNDEFINED_ID; | |
1124 | + break; | |
1125 | + | |
1126 | + case ACL_USER: | |
1127 | + case ACL_GROUP: | |
1128 | + value = (char *)value + sizeof(reiserfs_acl_entry); | |
1129 | + if ((char *)value > end) | |
1130 | + goto fail; | |
1131 | + acl->a_entries[n].e_id = | |
1132 | + le32_to_cpu(entry->e_id); | |
1133 | + break; | |
1134 | + | |
1135 | + default: | |
1136 | + goto fail; | |
1137 | + } | |
1138 | + } | |
1139 | + if (value != end) | |
1140 | + goto fail; | |
1141 | + return acl; | |
1142 | + | |
1143 | +fail: | |
1144 | + posix_acl_release(acl); | |
1145 | + return ERR_PTR(-EINVAL); | |
1146 | +} | |
1147 | + | |
1148 | +/* | |
1149 | + * Convert from in-memory to filesystem representation. | |
1150 | + */ | |
1151 | +static void * | |
1152 | +posix_acl_to_disk(const struct posix_acl *acl, size_t *size) | |
1153 | +{ | |
1154 | + reiserfs_acl_header *ext_acl; | |
1155 | + char *e; | |
1156 | + int n; | |
1157 | + | |
1158 | + *size = reiserfs_acl_size(acl->a_count); | |
1159 | + ext_acl = (reiserfs_acl_header *)kmalloc(sizeof(reiserfs_acl_header) + | |
1160 | + acl->a_count * sizeof(reiserfs_acl_entry), GFP_NOFS); | |
1161 | + if (!ext_acl) | |
1162 | + return ERR_PTR(-ENOMEM); | |
1163 | + ext_acl->a_version = cpu_to_le32(REISERFS_ACL_VERSION); | |
1164 | + e = (char *)ext_acl + sizeof(reiserfs_acl_header); | |
1165 | + for (n=0; n < acl->a_count; n++) { | |
1166 | + reiserfs_acl_entry *entry = (reiserfs_acl_entry *)e; | |
1167 | + entry->e_tag = cpu_to_le16(acl->a_entries[n].e_tag); | |
1168 | + entry->e_perm = cpu_to_le16(acl->a_entries[n].e_perm); | |
1169 | + switch(acl->a_entries[n].e_tag) { | |
1170 | + case ACL_USER: | |
1171 | + case ACL_GROUP: | |
1172 | + entry->e_id = | |
1173 | + cpu_to_le32(acl->a_entries[n].e_id); | |
1174 | + e += sizeof(reiserfs_acl_entry); | |
1175 | + break; | |
1176 | + | |
1177 | + case ACL_USER_OBJ: | |
1178 | + case ACL_GROUP_OBJ: | |
1179 | + case ACL_MASK: | |
1180 | + case ACL_OTHER: | |
1181 | + e += sizeof(reiserfs_acl_entry_short); | |
1182 | + break; | |
1183 | + | |
1184 | + default: | |
1185 | + goto fail; | |
1186 | + } | |
1187 | + } | |
1188 | + return (char *)ext_acl; | |
1189 | + | |
1190 | +fail: | |
1191 | + kfree(ext_acl); | |
1192 | + return ERR_PTR(-EINVAL); | |
1193 | +} | |
1194 | + | |
1195 | +/* | |
1196 | + * Inode operation get_posix_acl(). | |
1197 | + * | |
1198 | + * inode->i_sem: down | |
1199 | + * BKL held [before 2.5.x] | |
1200 | + */ | |
1201 | +struct posix_acl * | |
1202 | +reiserfs_get_acl(struct inode *inode, int type) | |
1203 | +{ | |
1204 | + char *name, *value; | |
1205 | + struct posix_acl *acl, **p_acl; | |
1206 | + size_t size; | |
1207 | + int retval; | |
1208 | + | |
1209 | + switch (type) { | |
1210 | + case ACL_TYPE_ACCESS: | |
1211 | + name = XATTR_NAME_ACL_ACCESS; | |
1212 | + p_acl = &inode->u.reiserfs_i.i_acl_access; | |
1213 | + break; | |
1214 | + case ACL_TYPE_DEFAULT: | |
1215 | + name = XATTR_NAME_ACL_DEFAULT; | |
1216 | + p_acl = &inode->u.reiserfs_i.i_acl_default; | |
1217 | + break; | |
1218 | + default: | |
1219 | + return ERR_PTR (-EINVAL); | |
1220 | + } | |
1221 | + | |
1222 | + if (IS_ERR (*p_acl)) { | |
1223 | + if (PTR_ERR (*p_acl) == -ENODATA) | |
1224 | + return NULL; | |
1225 | + } else if (*p_acl != NULL) | |
1226 | + return posix_acl_dup (*p_acl); | |
1227 | + | |
1228 | + size = reiserfs_xattr_get (inode, name, NULL, 0); | |
1229 | + if ((int)size < 0) { | |
1230 | + if (size == -ENODATA || size == -ENOSYS) { | |
1231 | + *p_acl = ERR_PTR (-ENODATA); | |
1232 | + return NULL; | |
1233 | + } | |
1234 | + return ERR_PTR (size); | |
1235 | + } | |
1236 | + | |
1237 | + value = kmalloc (size, GFP_NOFS); | |
1238 | + if (!value) | |
1239 | + return ERR_PTR (-ENOMEM); | |
1240 | + | |
1241 | + retval = reiserfs_xattr_get(inode, name, value, size); | |
1242 | + if (retval == -ENODATA || retval == -ENOSYS) { | |
1243 | + /* This shouldn't actually happen as it should have | |
1244 | + been caught above.. but just in case */ | |
1245 | + acl = NULL; | |
1246 | + *p_acl = ERR_PTR (-ENODATA); | |
1247 | + } else if (retval < 0) { | |
1248 | + acl = ERR_PTR(retval); | |
1249 | + } else { | |
1250 | + acl = posix_acl_from_disk(value, retval); | |
1251 | + *p_acl = posix_acl_dup (acl); | |
1252 | + } | |
1253 | + | |
1254 | + kfree(value); | |
1255 | + return acl; | |
1256 | +} | |
1257 | + | |
1258 | +/* | |
1259 | + * Inode operation set_posix_acl(). | |
1260 | + * | |
1261 | + * inode->i_sem: down | |
1262 | + * BKL held [before 2.5.x] | |
1263 | + */ | |
1264 | +int | |
1265 | +reiserfs_set_acl(struct inode *inode, int type, struct posix_acl *acl) | |
1266 | +{ | |
1267 | + char *name; | |
1268 | + void *value = NULL; | |
1269 | + struct posix_acl **p_acl; | |
1270 | + size_t size; | |
1271 | + int error; | |
1272 | + | |
1273 | + if (S_ISLNK(inode->i_mode)) | |
1274 | + return -EOPNOTSUPP; | |
1275 | + | |
1276 | + | |
1277 | + switch (type) { | |
1278 | + case ACL_TYPE_ACCESS: | |
1279 | + name = XATTR_NAME_ACL_ACCESS; | |
1280 | + p_acl = &inode->u.reiserfs_i.i_acl_access; | |
1281 | + if (acl) { | |
1282 | + mode_t mode = inode->i_mode; | |
1283 | + error = posix_acl_equiv_mode (acl, &mode); | |
1284 | + if (error < 0) | |
1285 | + return error; | |
1286 | + else { | |
1287 | + inode->i_mode = mode; | |
1288 | + if (error == 0) | |
1289 | + acl = NULL; | |
1290 | + } | |
1291 | + } | |
1292 | + break; | |
1293 | + case ACL_TYPE_DEFAULT: | |
1294 | + name = XATTR_NAME_ACL_DEFAULT; | |
1295 | + p_acl = &inode->u.reiserfs_i.i_acl_default; | |
1296 | + if (!S_ISDIR (inode->i_mode)) | |
1297 | + return acl ? -EACCES : 0; | |
1298 | + break; | |
1299 | + default: | |
1300 | + return -EINVAL; | |
1301 | + } | |
1302 | + | |
1303 | + if (acl) { | |
1304 | + value = posix_acl_to_disk(acl, &size); | |
1305 | + if (IS_ERR(value)) | |
1306 | + return (int)PTR_ERR(value); | |
1307 | + error = reiserfs_xattr_set(inode, name, value, size, 0); | |
1308 | + } else { | |
1309 | + error = reiserfs_xattr_del (inode, name); | |
1310 | + if (error == -ENODATA) | |
1311 | + error = 0; | |
1312 | + } | |
1313 | + | |
1314 | + if (value) | |
1315 | + kfree(value); | |
1316 | + | |
1317 | + if (!error) { | |
1318 | + /* Release the old one */ | |
1319 | + if (!IS_ERR (*p_acl) && *p_acl) | |
1320 | + posix_acl_release (*p_acl); | |
1321 | + | |
1322 | + if (acl == NULL) | |
1323 | + *p_acl = ERR_PTR (-ENODATA); | |
1324 | + else | |
1325 | + *p_acl = posix_acl_dup (acl); | |
1326 | + } | |
1327 | + | |
1328 | + return error; | |
1329 | +} | |
1330 | + | |
1331 | +/* dir->i_sem: down, | |
1332 | + * inode is new and not released into the wild yet */ | |
1333 | +int | |
1334 | +reiserfs_inherit_default_acl (struct inode *dir, struct dentry *dentry, struct inode *inode) | |
1335 | +{ | |
1336 | + struct posix_acl *acl; | |
1337 | + int err = 0; | |
1338 | + | |
1339 | + /* ACLs only get applied to files and directories */ | |
1340 | + if (S_ISLNK (inode->i_mode)) | |
1341 | + return 0; | |
1342 | + | |
1343 | + /* ACLs can only be used on "new" objects, so if it's an old object | |
1344 | + * there is nothing to inherit from */ | |
1345 | + if (get_inode_sd_version (dir) == STAT_DATA_V1) | |
1346 | + goto apply_umask; | |
1347 | + | |
1348 | + /* Don't apply ACLs to objects in the .reiserfs_priv tree.. This | |
1349 | + * would be useless since permissions are ignored, and a pain because | |
1350 | + * it introduces locking cycles */ | |
1351 | + if (is_reiserfs_priv_object (dir)) { | |
1352 | + inode->u.reiserfs_i.i_flags |= i_priv_object; | |
1353 | + goto apply_umask; | |
1354 | + } | |
1355 | + | |
1356 | + acl = reiserfs_get_acl (dir, ACL_TYPE_DEFAULT); | |
1357 | + if (IS_ERR (acl)) { | |
1358 | + if (PTR_ERR (acl) == -ENODATA) | |
1359 | + goto apply_umask; | |
1360 | + return PTR_ERR (acl); | |
1361 | + } | |
1362 | + | |
1363 | + if (acl) { | |
1364 | + struct posix_acl *acl_copy; | |
1365 | + mode_t mode = inode->i_mode; | |
1366 | + int need_acl; | |
1367 | + | |
1368 | + /* Copy the default ACL to the default ACL of a new directory */ | |
1369 | + if (S_ISDIR (inode->i_mode)) { | |
1370 | + err = reiserfs_set_acl (inode, ACL_TYPE_DEFAULT, acl); | |
1371 | + if (err) | |
1372 | + goto cleanup; | |
1373 | + } | |
1374 | + | |
1375 | + /* Now we reconcile the new ACL and the mode, | |
1376 | + potentially modifying both */ | |
1377 | + acl_copy = posix_acl_clone (acl, GFP_NOFS); | |
1378 | + if (!acl_copy) { | |
1379 | + err = -ENOMEM; | |
1380 | + goto cleanup; | |
1381 | + } | |
1382 | + | |
1383 | + | |
1384 | + need_acl = posix_acl_create_masq (acl_copy, &mode); | |
1385 | + if (need_acl >= 0) { | |
1386 | + if (mode != inode->i_mode) { | |
1387 | + inode->i_mode = mode; | |
1388 | + } | |
1389 | + | |
1390 | + /* If we need an ACL.. */ | |
1391 | + if (need_acl > 0) { | |
1392 | + err = reiserfs_set_acl (inode, ACL_TYPE_ACCESS, acl_copy); | |
1393 | + if (err) | |
1394 | + goto cleanup_copy; | |
1395 | + } | |
1396 | + } | |
1397 | +cleanup_copy: | |
1398 | + posix_acl_release (acl_copy); | |
1399 | +cleanup: | |
1400 | + posix_acl_release (acl); | |
1401 | + } else { | |
1402 | +apply_umask: | |
1403 | + /* no ACL, apply umask */ | |
1404 | + inode->i_mode &= ~current->fs->umask; | |
1405 | + } | |
1406 | + | |
1407 | + return err; | |
1408 | +} | |
1409 | + | |
1410 | +/* Looks up and caches the result of the default ACL. | |
1411 | + * We do this so that we don't need to carry the xattr_sem into | |
1412 | + * reiserfs_new_inode if we don't need to */ | |
1413 | +int | |
1414 | +reiserfs_cache_default_acl (struct inode *inode) | |
1415 | +{ | |
1416 | + int ret = 0; | |
1417 | + if (reiserfs_posixacl (inode->i_sb) && | |
1418 | + !is_reiserfs_priv_object (inode)) { | |
1419 | + struct posix_acl *acl; | |
1420 | + reiserfs_read_lock_xattrs (inode->i_sb); | |
1421 | + acl = reiserfs_get_acl (inode, ACL_TYPE_DEFAULT); | |
1422 | + reiserfs_read_unlock_xattrs (inode->i_sb); | |
1423 | + ret = acl ? 1 : 0; | |
1424 | + posix_acl_release (acl); | |
1425 | + } | |
1426 | + | |
1427 | + return ret; | |
1428 | +} | |
1429 | + | |
1430 | +static int | |
1431 | +__reiserfs_permission (struct inode *inode, int mask, int need_lock) | |
1432 | +{ | |
1433 | + int mode = inode->i_mode; | |
1434 | + | |
1435 | + /* Nobody gets write access to a read-only fs */ | |
1436 | + if ((mask & MAY_WRITE) && IS_RDONLY(inode) && | |
1437 | + (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))) | |
1438 | + return -EROFS; | |
1439 | + | |
1440 | + /* Nobody gets write access to an immutable file */ | |
1441 | + if ((mask & MAY_WRITE) && IS_IMMUTABLE(inode)) | |
1442 | + return -EACCES; | |
1443 | + | |
1444 | + /* We don't do permission checks on the internal objects. | |
1445 | + * Permissions are determined by the "owning" object. */ | |
1446 | + if (is_reiserfs_priv_object (inode)) | |
1447 | + return 0; | |
1448 | + | |
1449 | + if (current->fsuid == inode->i_uid) { | |
1450 | + mode >>= 6; | |
1451 | + } else if (reiserfs_posixacl(inode->i_sb) && | |
1452 | + get_inode_sd_version (inode) != STAT_DATA_V1) { | |
1453 | + struct posix_acl *acl; | |
1454 | + | |
1455 | + /* ACL can't contain additional permissions if | |
1456 | + the ACL_MASK entry is 0 */ | |
1457 | + if (!(mode & S_IRWXG)) | |
1458 | + goto check_groups; | |
1459 | + | |
1460 | + if (need_lock) | |
1461 | + reiserfs_read_lock_xattrs (inode->i_sb); | |
1462 | + acl = reiserfs_get_acl (inode, ACL_TYPE_ACCESS); | |
1463 | + if (need_lock) | |
1464 | + reiserfs_read_unlock_xattrs (inode->i_sb); | |
1465 | + if (IS_ERR (acl)) { | |
1466 | + if (PTR_ERR (acl) == -ENODATA) | |
1467 | + goto check_groups; | |
1468 | + return PTR_ERR (acl); | |
1469 | + } | |
1470 | + | |
1471 | + if (acl) { | |
1472 | + int err = posix_acl_permission (inode, acl, mask); | |
1473 | + posix_acl_release (acl); | |
1474 | + if (err == -EACCES) { | |
1475 | + goto check_capabilities; | |
1476 | + } | |
1477 | + return err; | |
1478 | + } else { | |
1479 | + goto check_groups; | |
1480 | + } | |
1481 | + | |
1482 | + } else { | |
1483 | +check_groups: | |
1484 | + if (in_group_p(inode->i_gid)) | |
1485 | + mode >>= 3; | |
1486 | + } | |
1487 | + if ((mode & mask & S_IRWXO) == mask) | |
1488 | + return 0; | |
1489 | + | |
1490 | +check_capabilities: | |
1491 | + /* Allowed to override Discretionary Access Control? */ | |
1492 | + if ((mask & (MAY_READ|MAY_WRITE)) || (inode->i_mode & S_IXUGO)) | |
1493 | + if (capable(CAP_DAC_OVERRIDE)) | |
1494 | + return 0; | |
1495 | + /* Read and search granted if capable(CAP_DAC_READ_SEARCH) */ | |
1496 | + if (capable(CAP_DAC_READ_SEARCH) && ((mask == MAY_READ) || | |
1497 | + (S_ISDIR(inode->i_mode) && !(mask & MAY_WRITE)))) | |
1498 | + return 0; | |
1499 | + return -EACCES; | |
1500 | +} | |
1501 | + | |
1502 | +int | |
1503 | +reiserfs_permission (struct inode *inode, int mask) | |
1504 | +{ | |
1505 | + return __reiserfs_permission (inode, mask, 1); | |
1506 | +} | |
1507 | + | |
1508 | +int | |
1509 | +reiserfs_permission_locked (struct inode *inode, int mask) | |
1510 | +{ | |
1511 | + return __reiserfs_permission (inode, mask, 0); | |
1512 | +} | |
1513 | + | |
1514 | +int | |
1515 | +reiserfs_acl_chmod (struct inode *inode) | |
1516 | +{ | |
1517 | + struct posix_acl *acl, *clone; | |
1518 | + int error; | |
1519 | + | |
1520 | + if (S_ISLNK(inode->i_mode)) | |
1521 | + return -EOPNOTSUPP; | |
1522 | + | |
1523 | + if (get_inode_sd_version (inode) == STAT_DATA_V1 || | |
1524 | + !reiserfs_posixacl(inode->i_sb)) | |
1525 | + { | |
1526 | + return 0; | |
1527 | + } | |
1528 | + | |
1529 | + reiserfs_read_lock_xattrs (inode->i_sb); | |
1530 | + acl = reiserfs_get_acl(inode, ACL_TYPE_ACCESS); | |
1531 | + reiserfs_read_unlock_xattrs (inode->i_sb); | |
1532 | + if (!acl) | |
1533 | + return 0; | |
1534 | + if (IS_ERR(acl)) | |
1535 | + return PTR_ERR(acl); | |
1536 | + clone = posix_acl_clone(acl, GFP_NOFS); | |
1537 | + posix_acl_release(acl); | |
1538 | + if (!clone) | |
1539 | + return -ENOMEM; | |
1540 | + error = posix_acl_chmod_masq(clone, inode->i_mode); | |
1541 | + if (!error) { | |
1542 | + reiserfs_write_lock_xattrs (inode->i_sb); | |
1543 | + error = reiserfs_set_acl(inode, ACL_TYPE_ACCESS, clone); | |
1544 | + reiserfs_write_unlock_xattrs (inode->i_sb); | |
1545 | + } | |
1546 | + posix_acl_release(clone); | |
1547 | + return error; | |
1548 | +} | |
1549 | + | |
1550 | +static int | |
1551 | +posix_acl_access_get(struct inode *inode, const char *name, | |
1552 | + void *buffer, size_t size) | |
1553 | +{ | |
1554 | + if (strlen(name) != sizeof(XATTR_NAME_ACL_ACCESS)-1) | |
1555 | + return -EINVAL; | |
1556 | + return xattr_get_acl(inode, ACL_TYPE_ACCESS, buffer, size); | |
1557 | +} | |
1558 | + | |
1559 | +static int | |
1560 | +posix_acl_access_set(struct inode *inode, const char *name, | |
1561 | + const void *value, size_t size, int flags) | |
1562 | +{ | |
1563 | + if (strlen(name) != sizeof(XATTR_NAME_ACL_ACCESS)-1) | |
1564 | + return -EINVAL; | |
1565 | + return xattr_set_acl(inode, ACL_TYPE_ACCESS, value, size); | |
1566 | +} | |
1567 | + | |
1568 | +static int | |
1569 | +posix_acl_access_del (struct inode *inode, const char *name) | |
1570 | +{ | |
1571 | + struct posix_acl **acl = &inode->u.reiserfs_i.i_acl_access; | |
1572 | + if (strlen(name) != sizeof(XATTR_NAME_ACL_ACCESS)-1) | |
1573 | + return -EINVAL; | |
1574 | + if (!IS_ERR (*acl) && *acl) { | |
1575 | + posix_acl_release (*acl); | |
1576 | + *acl = ERR_PTR (-ENODATA); | |
1577 | + } | |
1578 | + | |
1579 | + return 0; | |
1580 | +} | |
1581 | + | |
1582 | +static int | |
1583 | +posix_acl_access_list (struct inode *inode, const char *name, int namelen, char *out) | |
1584 | +{ | |
1585 | + int len = namelen; | |
1586 | + if (!reiserfs_posixacl (inode->i_sb)) | |
1587 | + return 0; | |
1588 | + if (out) | |
1589 | + memcpy (out, name, len); | |
1590 | + | |
1591 | + return len; | |
1592 | +} | |
1593 | + | |
1594 | +struct reiserfs_xattr_handler posix_acl_access_handler = { | |
1595 | + prefix: XATTR_NAME_ACL_ACCESS, | |
1596 | + get: posix_acl_access_get, | |
1597 | + set: posix_acl_access_set, | |
1598 | + del: posix_acl_access_del, | |
1599 | + list: posix_acl_access_list, | |
1600 | +}; | |
1601 | + | |
1602 | +static int | |
1603 | +posix_acl_default_get (struct inode *inode, const char *name, | |
1604 | + void *buffer, size_t size) | |
1605 | +{ | |
1606 | + if (strlen(name) != sizeof(XATTR_NAME_ACL_DEFAULT)-1) | |
1607 | + return -EINVAL; | |
1608 | + return xattr_get_acl(inode, ACL_TYPE_DEFAULT, buffer, size); | |
1609 | +} | |
1610 | + | |
1611 | +static int | |
1612 | +posix_acl_default_set(struct inode *inode, const char *name, | |
1613 | + const void *value, size_t size, int flags) | |
1614 | +{ | |
1615 | + if (strlen(name) != sizeof(XATTR_NAME_ACL_DEFAULT)-1) | |
1616 | + return -EINVAL; | |
1617 | + return xattr_set_acl(inode, ACL_TYPE_DEFAULT, value, size); | |
1618 | +} | |
1619 | + | |
1620 | +static int | |
1621 | +posix_acl_default_del (struct inode *inode, const char *name) | |
1622 | +{ | |
1623 | + struct posix_acl **acl = &inode->u.reiserfs_i.i_acl_default; | |
1624 | + if (strlen(name) != sizeof(XATTR_NAME_ACL_DEFAULT)-1) | |
1625 | + return -EINVAL; | |
1626 | + if (!IS_ERR (*acl) && *acl) { | |
1627 | + posix_acl_release (*acl); | |
1628 | + *acl = ERR_PTR (-ENODATA); | |
1629 | + } | |
1630 | + | |
1631 | + return 0; | |
1632 | +} | |
1633 | + | |
1634 | +static int | |
1635 | +posix_acl_default_list (struct inode *inode, const char *name, int namelen, char *out) | |
1636 | +{ | |
1637 | + int len = namelen; | |
1638 | + if (!reiserfs_posixacl (inode->i_sb)) | |
1639 | + return 0; | |
1640 | + if (out) | |
1641 | + memcpy (out, name, len); | |
1642 | + | |
1643 | + return len; | |
1644 | +} | |
1645 | + | |
1646 | +struct reiserfs_xattr_handler posix_acl_default_handler = { | |
1647 | + prefix: XATTR_NAME_ACL_DEFAULT, | |
1648 | + get: posix_acl_default_get, | |
1649 | + set: posix_acl_default_set, | |
1650 | + del: posix_acl_default_del, | |
1651 | + list: posix_acl_default_list, | |
1652 | +}; | |
1653 | + | |
1654 | +int __init | |
1655 | +reiserfs_xattr_posix_acl_init (void) | |
1656 | +{ | |
1657 | + int err; | |
1658 | + err = reiserfs_xattr_register_handler (&posix_acl_access_handler); | |
1659 | + if (!err) | |
1660 | + err = reiserfs_xattr_register_handler (&posix_acl_default_handler); | |
1661 | + return err; | |
1662 | +} | |
1663 | + | |
1664 | +int | |
1665 | +reiserfs_xattr_posix_acl_exit (void) | |
1666 | +{ | |
1667 | + int err; | |
1668 | + err = reiserfs_xattr_unregister_handler (&posix_acl_access_handler); | |
1669 | + if (!err) | |
1670 | + err = reiserfs_xattr_unregister_handler (&posix_acl_default_handler); | |
1671 | + return err; | |
1672 | +} | |
51560e02 AM |
1673 | diff -urN linux-2.4.22.org/fs/reiserfs/xattr.c linux-2.4.22/fs/reiserfs/xattr.c |
1674 | --- linux-2.4.22.org/fs/reiserfs/xattr.c 1970-01-01 01:00:00.000000000 +0100 | |
1675 | +++ linux-2.4.22/fs/reiserfs/xattr.c 2003-11-21 15:26:23.000000000 +0100 | |
e57e653a JR |
1676 | @@ -0,0 +1,1665 @@ |
1677 | +/* | |
1678 | + * linux/fs/reiserfs/xattr.c | |
1679 | + * | |
1680 | + * Copyright (c) 2002 by Jeff Mahoney, <jeffm@suse.com> | |
1681 | + * | |
1682 | + */ | |
1683 | + | |
1684 | +/* | |
1685 | + * In order to implement EA/ACLs in a clean, backwards compatible manner, | |
1686 | + * they are implemented as files in a "private" directory. | |
1687 | + * Each EA is in it's own file, with the directory layout like so (/ is assumed | |
1688 | + * to be relative to fs root). Inside the /.reiserfs_priv/xattrs directory, | |
1689 | + * directories named using the capital-hex form of the objectid and | |
1690 | + * generation number are used. Inside each directory are individual files | |
1691 | + * named with the name of the extended attribute. | |
1692 | + * | |
1693 | + * So, for objectid 12648430, we could have: | |
1694 | + * /.reiserfs_priv/xattrs/C0FFEE.0/system.posix_acl_access | |
1695 | + * /.reiserfs_priv/xattrs/C0FFEE.0/system.posix_acl_default | |
1696 | + * /.reiserfs_priv/xattrs/C0FFEE.0/user.Content-Type | |
1697 | + * .. or similar. | |
1698 | + * | |
1699 | + * The file contents are the text of the EA. The size is known based on the | |
1700 | + * stat data describing the file. | |
1701 | + * | |
1702 | + * In the case of system.posix_acl_access and system.posix_acl_default, since | |
1703 | + * these are special cases for filesystem ACLs, they are interpreted by the | |
1704 | + * kernel, in addition, they are negatively and positively cached and attached | |
1705 | + * to the inode so that unnecessary lookups are avoided. | |
1706 | + */ | |
1707 | + | |
1708 | +#include <linux/reiserfs_fs.h> | |
1709 | +#include <linux/dcache.h> | |
1710 | +#include <linux/errno.h> | |
1711 | +#include <linux/fs.h> | |
1712 | +#include <linux/file.h> | |
1713 | +#include <linux/pagemap.h> | |
1714 | +#include <linux/xattr.h> | |
1715 | +#include <linux/reiserfs_xattr.h> | |
1716 | +#include <linux/mbcache.h> | |
1717 | +#include <asm/uaccess.h> | |
1718 | +#include <asm/checksum.h> | |
1719 | +#include <linux/smp_lock.h> | |
1720 | +#include <linux/stat.h> | |
1721 | +#include <asm/semaphore.h> | |
1722 | + | |
1723 | +#define FL_READONLY 128 | |
1724 | +#define FL_DIR_SEM_HELD 256 | |
1725 | +#define PRIVROOT_NAME ".reiserfs_priv" | |
1726 | +#define XAROOT_NAME "xattrs" | |
1727 | + | |
1728 | +#ifdef CONFIG_REISERFS_FS_XATTR_SHARING | |
1729 | +# error "xattr sharing is not fully implemented and buggy. DO NOT USE." | |
1730 | +static int reiserfs_xattr_link_to_inode (struct inode *xattr_inode, | |
1731 | + struct inode *dst_inode, | |
1732 | + const char *dst_name); | |
1733 | +#endif | |
1734 | + | |
1735 | +static struct reiserfs_xattr_handler *find_xattr_handler_prefix (const char *prefix); | |
1736 | + | |
1737 | +/* Return a dentry (or NULL) for the root of the reiserfs-private directory. | |
1738 | + * The "xattrs" directory is contained here, as may other things in the future | |
1739 | + */ | |
1740 | +static struct dentry * | |
1741 | +reiserfs_get_priv_root (struct super_block *s) | |
1742 | +{ | |
1743 | + struct dentry *dentry = NULL; | |
1744 | + struct qstr privroot; | |
1745 | + int retval; | |
1746 | + struct reiserfs_dir_entry de; | |
1747 | + INITIALIZE_PATH (path); | |
1748 | + | |
1749 | + privroot.name = PRIVROOT_NAME; | |
1750 | + privroot.len = strlen (privroot.name); | |
1751 | + | |
1752 | + de.de_gen_number_bit_string = 0; | |
1753 | + retval = reiserfs_find_entry (s->s_root->d_inode, privroot.name, | |
1754 | + privroot.len, &path, &de); | |
1755 | + pathrelse (&path); | |
1756 | + if (retval == NAME_FOUND) { | |
1757 | + struct inode *inode; | |
1758 | + inode = reiserfs_iget (s, (struct cpu_key *)&(de.de_dir_id)); | |
1759 | + | |
1760 | + /* We don't want this entry hashed. Otherwise, we can't | |
1761 | + * poison lookup() and readdir() against it */ | |
1762 | + if (inode && !IS_ERR (inode)) { | |
1763 | + privroot.hash = full_name_hash (privroot.name, privroot.len); | |
1764 | + dentry = d_alloc (s->s_root, &privroot); | |
1765 | + | |
1766 | + if (dentry) | |
1767 | + d_instantiate (dentry, inode); | |
1768 | + inode->u.reiserfs_i.i_flags |= i_priv_object; | |
1769 | + } | |
1770 | + } | |
1771 | + | |
1772 | + return dentry; | |
1773 | +} | |
1774 | + | |
1775 | + | |
1776 | +static struct dentry * | |
1777 | +reiserfs_create_priv_root (struct super_block *sb) | |
1778 | +{ | |
1779 | + int ret; | |
1780 | + struct inode *inode = sb->s_root->d_inode; | |
1781 | + struct dentry *privroot; | |
1782 | + struct qstr xa; | |
1783 | + | |
1784 | + xa.name = PRIVROOT_NAME; | |
1785 | + xa.len = strlen (xa.name); | |
1786 | + xa.hash = full_name_hash (xa.name, xa.len); | |
1787 | + privroot = d_alloc (sb->s_root, &xa); | |
1788 | + if (!privroot) | |
1789 | + return ERR_PTR (-ENOMEM); | |
1790 | + | |
1791 | + down (&inode->i_sem); | |
1792 | + ret = inode->i_op->mkdir (inode, privroot, 0700); | |
1793 | + up (&inode->i_sem); | |
1794 | + | |
1795 | + if (ret) { | |
1796 | + dput (privroot); | |
1797 | + return ERR_PTR (ret); | |
1798 | + } | |
1799 | + | |
1800 | + if (privroot->d_inode) { | |
1801 | + reiserfs_warning ("reiserfs: Created %s on %s - reserved for " | |
1802 | + "xattr storage.\n", PRIVROOT_NAME, | |
1803 | + bdevname (sb->s_dev)); | |
1804 | + privroot->d_inode->u.reiserfs_i.i_flags |= i_priv_object; | |
1805 | + d_drop (privroot); | |
1806 | + } | |
1807 | + return privroot; | |
1808 | +} | |
1809 | + | |
1810 | +static struct dentry * | |
1811 | +create_xa_root (struct super_block *sb) | |
1812 | +{ | |
1813 | + struct dentry *privroot = dget (sb->u.reiserfs_sb.priv_root); | |
1814 | + struct dentry *xaroot; | |
1815 | + | |
1816 | + /* This needs to be created at mount-time */ | |
1817 | + if (!privroot) | |
1818 | + return ERR_PTR(-EOPNOTSUPP); | |
1819 | + | |
1820 | + xaroot = lookup_one_len (XAROOT_NAME, privroot, strlen (XAROOT_NAME)); | |
1821 | + if (IS_ERR (xaroot)) { | |
1822 | + goto out; | |
1823 | + } else if (!xaroot->d_inode) { | |
1824 | + int err; | |
1825 | + down (&privroot->d_inode->i_sem); | |
1826 | + err = privroot->d_inode->i_op->mkdir (privroot->d_inode, xaroot, 0700); | |
1827 | + up (&privroot->d_inode->i_sem); | |
1828 | + | |
1829 | + if (err) { | |
1830 | + dput (xaroot); | |
1831 | + dput (privroot); | |
1832 | + return ERR_PTR (err); | |
1833 | + } | |
1834 | + sb->u.reiserfs_sb.xattr_root = dget (xaroot); | |
1835 | + } | |
1836 | + | |
1837 | +out: | |
1838 | + dput (privroot); | |
1839 | + return xaroot; | |
1840 | +} | |
1841 | + | |
1842 | +/* This will return a dentry, or error, refering to the xa root directory. | |
1843 | + * If the xa root doesn't exist yet, the dentry will be returned without | |
1844 | + * an associated inode. This dentry can be used with ->mkdir to create | |
1845 | + * the xa directory. */ | |
1846 | +static struct dentry * | |
1847 | +__get_xa_root (struct super_block *s) | |
1848 | +{ | |
1849 | + struct dentry *privroot = dget (s->u.reiserfs_sb.priv_root); | |
1850 | + struct dentry *xaroot = NULL; | |
1851 | + | |
1852 | + if (IS_ERR (privroot) || !privroot) | |
1853 | + return privroot; | |
1854 | + | |
1855 | + xaroot = lookup_one_len (XAROOT_NAME, privroot, strlen (XAROOT_NAME)); | |
1856 | + if (IS_ERR (xaroot)) { | |
1857 | + goto out; | |
1858 | + } else if (!xaroot->d_inode) { | |
1859 | + dput (xaroot); | |
1860 | + xaroot = NULL; | |
1861 | + goto out; | |
1862 | + } | |
1863 | + | |
1864 | + s->u.reiserfs_sb.xattr_root = dget (xaroot); | |
1865 | + | |
1866 | +out: | |
1867 | + dput (privroot); | |
1868 | + return xaroot; | |
1869 | +} | |
1870 | + | |
1871 | +/* Returns the dentry (or NULL) referring to the root of the extended | |
1872 | + * attribute directory tree. If it has already been retreived, it is used. | |
1873 | + * Otherwise, we attempt to retreive it from disk. It may also return | |
1874 | + * a pointer-encoded error. | |
1875 | + */ | |
1876 | +static inline struct dentry * | |
1877 | +get_xa_root (struct super_block *s) | |
1878 | +{ | |
1879 | + struct dentry *dentry = s->u.reiserfs_sb.xattr_root; | |
1880 | + | |
1881 | + if (!dentry) | |
1882 | + dentry = __get_xa_root (s); | |
1883 | + else | |
1884 | + dget (dentry); | |
1885 | + return dentry; | |
1886 | +} | |
1887 | + | |
1888 | +/* Same as above, but only returns a valid dentry or NULL */ | |
1889 | +struct dentry * | |
1890 | +reiserfs_get_xa_root (struct super_block *sb) | |
1891 | +{ | |
1892 | + struct dentry *dentry; | |
1893 | + | |
1894 | + dentry = get_xa_root (sb); | |
1895 | + if (IS_ERR (dentry)) { | |
1896 | + dentry = NULL; | |
1897 | + } else if (dentry && !dentry->d_inode) { | |
1898 | + dput (dentry); | |
1899 | + dentry = NULL; | |
1900 | + } | |
1901 | + | |
1902 | + return dentry; | |
1903 | +} | |
1904 | + | |
1905 | +/* Opens the directory corresponding to the inode's extended attribute store. | |
1906 | + * If flags allow, the tree to the directory may be created. If creation is | |
1907 | + * prohibited, -ENODATA is returned. */ | |
1908 | +static struct dentry * | |
1909 | +open_xa_dir (const struct inode *inode, int flags) | |
1910 | +{ | |
1911 | + struct dentry *xaroot, *xadir; | |
1912 | + char namebuf[17]; | |
1913 | + | |
1914 | + xaroot = get_xa_root (inode->i_sb); | |
1915 | + if (IS_ERR (xaroot)) { | |
1916 | + return xaroot; | |
1917 | + } else if (!xaroot) { | |
1918 | + if (flags == 0 || flags & XATTR_CREATE) { | |
1919 | + xaroot = create_xa_root (inode->i_sb); | |
1920 | + if (IS_ERR (xaroot)) | |
1921 | + return xaroot; | |
1922 | + } | |
1923 | + if (!xaroot) | |
1924 | + return ERR_PTR (-ENODATA); | |
1925 | + } | |
1926 | + | |
1927 | + /* ok, we have xaroot open */ | |
1928 | + | |
1929 | + snprintf (namebuf, sizeof (namebuf), "%X.%X", | |
1930 | + le32_to_cpu (INODE_PKEY (inode)->k_objectid), | |
1931 | + inode->i_generation); | |
1932 | + xadir = lookup_one_len (namebuf, xaroot, strlen (namebuf)); | |
1933 | + if (IS_ERR (xadir)) { | |
1934 | + dput (xaroot); | |
1935 | + return xadir; | |
1936 | + } | |
1937 | + | |
1938 | + if (!xadir->d_inode) { | |
1939 | + int err; | |
1940 | + if (flags == 0 || flags & XATTR_CREATE) { | |
1941 | + /* Although there is nothing else trying to create this directory, | |
1942 | + * another directory with the same hash may be created, so we need | |
1943 | + * to protect against that */ | |
1944 | + err = xaroot->d_inode->i_op->mkdir (xaroot->d_inode, xadir, 0700); | |
1945 | + if (err) { | |
1946 | + dput (xaroot); | |
1947 | + dput (xadir); | |
1948 | + return ERR_PTR (err); | |
1949 | + } | |
1950 | + } | |
1951 | + if (!xadir->d_inode) { | |
1952 | + dput (xaroot); | |
1953 | + dput (xadir); | |
1954 | + return ERR_PTR (-ENODATA); | |
1955 | + } | |
1956 | + } | |
1957 | + | |
1958 | + dput (xaroot); | |
1959 | + return xadir; | |
1960 | +} | |
1961 | + | |
1962 | +/* Returns a dentry corresponding to a specific extended attribute file | |
1963 | + * for the inode. If flags allow, the file is created. Otherwise, a | |
1964 | + * valid or negative dentry, or an error is returned. */ | |
1965 | +static struct dentry * | |
1966 | +get_xa_file_dentry (const struct inode *inode, const char *name, int flags) | |
1967 | +{ | |
1968 | + struct dentry *xadir, *xafile; | |
1969 | + int err = 0; | |
1970 | + | |
1971 | + xadir = open_xa_dir (inode, flags); | |
1972 | + if (IS_ERR (xadir)) { | |
1973 | + return ERR_PTR (PTR_ERR (xadir)); | |
1974 | + } else if (xadir && !xadir->d_inode) { | |
1975 | + dput (xadir); | |
1976 | + return ERR_PTR (-ENODATA); | |
1977 | + } | |
1978 | + | |
1979 | + xafile = lookup_one_len (name, xadir, strlen (name)); | |
1980 | + if (IS_ERR (xafile)) { | |
1981 | + dput (xadir); | |
1982 | + return ERR_PTR (PTR_ERR (xafile)); | |
1983 | + } | |
1984 | + | |
1985 | + if (xafile->d_inode) { /* file exists */ | |
1986 | + if (flags & XATTR_CREATE) { | |
1987 | + err = -EEXIST; | |
1988 | + dput (xafile); | |
1989 | + goto out; | |
1990 | + } | |
1991 | + } else if (flags & XATTR_REPLACE || flags & FL_READONLY) { | |
1992 | + goto out; | |
1993 | + } else { | |
1994 | + /* inode->i_sem is down, so nothing else can try to create | |
1995 | + * the same xattr */ | |
1996 | + err = xadir->d_inode->i_op->create (xadir->d_inode, xafile, | |
1997 | + 0700|S_IFREG); | |
1998 | + | |
1999 | + if (err) { | |
2000 | + dput (xafile); | |
2001 | + goto out; | |
2002 | + } | |
2003 | + } | |
2004 | + | |
2005 | +out: | |
2006 | + dput (xadir); | |
2007 | + if (err) | |
2008 | + xafile = ERR_PTR (err); | |
2009 | + return xafile; | |
2010 | +} | |
2011 | + | |
2012 | + | |
2013 | +/* Opens a file pointer to the attribute associated with inode */ | |
2014 | +static struct file * | |
2015 | +open_xa_file (const struct inode *inode, const char *name, int flags) | |
2016 | +{ | |
2017 | + struct dentry *xafile; | |
2018 | + struct file *fp; | |
2019 | + | |
2020 | + xafile = get_xa_file_dentry (inode, name, flags); | |
2021 | + if (IS_ERR (xafile)) | |
2022 | + return ERR_PTR (PTR_ERR (xafile)); | |
2023 | + else if (!xafile->d_inode) { | |
2024 | + dput (xafile); | |
2025 | + return ERR_PTR (-ENODATA); | |
2026 | + } | |
2027 | + | |
2028 | + fp = dentry_open (xafile, NULL, O_RDWR); | |
2029 | + /* dentry_open dputs the dentry if it fails */ | |
2030 | + | |
2031 | + return fp; | |
2032 | +} | |
2033 | + | |
2034 | + | |
2035 | +/* | |
2036 | + * this is very similar to fs/reiserfs/dir.c:reiserfs_readdir, but | |
2037 | + * we need to drop the path before calling the filldir struct. That | |
2038 | + * would be a big performance hit to the non-xattr case, so I've copied | |
2039 | + * the whole thing for now. --clm | |
2040 | + * | |
2041 | + * the big difference is that I go backwards through the directory, | |
2042 | + * and don't mess with f->f_pos, but the idea is the same. Do some | |
2043 | + * action on each and every entry in the directory. | |
2044 | + * | |
2045 | + * we're called with i_sem held, so there are no worries about the directory | |
2046 | + * changing underneath us. | |
2047 | + */ | |
2048 | +static int __xattr_readdir(struct file * filp, void * dirent, filldir_t filldir) | |
2049 | +{ | |
2050 | + struct inode *inode = filp->f_dentry->d_inode; | |
2051 | + struct cpu_key pos_key; /* key of current position in the directory (key of directory entry) */ | |
2052 | + INITIALIZE_PATH (path_to_entry); | |
2053 | + struct buffer_head * bh; | |
2054 | + int entry_num; | |
2055 | + struct item_head * ih, tmp_ih; | |
2056 | + int search_res; | |
2057 | + char * local_buf; | |
2058 | + loff_t next_pos; | |
2059 | + char small_buf[32] ; /* avoid kmalloc if we can */ | |
2060 | + struct reiserfs_de_head *deh; | |
2061 | + int d_reclen; | |
2062 | + char * d_name; | |
2063 | + off_t d_off; | |
2064 | + ino_t d_ino; | |
2065 | + struct reiserfs_dir_entry de; | |
2066 | + | |
2067 | + | |
2068 | + /* form key for search the next directory entry using f_pos field of | |
2069 | + file structure */ | |
2070 | + next_pos = max_reiserfs_offset(inode); | |
2071 | + | |
2072 | + while (1) { | |
2073 | +research: | |
2074 | + if (next_pos <= DOT_DOT_OFFSET) | |
2075 | + break; | |
2076 | + make_cpu_key (&pos_key, inode, next_pos, TYPE_DIRENTRY, 3); | |
2077 | + | |
2078 | + search_res = search_by_entry_key(inode->i_sb, &pos_key, &path_to_entry, &de); | |
2079 | + if (search_res == IO_ERROR) { | |
2080 | + // FIXME: we could just skip part of directory which could | |
2081 | + // not be read | |
2082 | + pathrelse(&path_to_entry); | |
2083 | + return -EIO; | |
2084 | + } | |
2085 | + | |
2086 | + if (search_res == NAME_NOT_FOUND) | |
2087 | + de.de_entry_num--; | |
2088 | + | |
2089 | + set_de_name_and_namelen(&de); | |
2090 | + entry_num = de.de_entry_num; | |
2091 | + deh = &(de.de_deh[entry_num]); | |
2092 | + | |
2093 | + bh = de.de_bh; | |
2094 | + ih = de.de_ih; | |
2095 | + | |
2096 | + if (!is_direntry_le_ih(ih)) { | |
2097 | +reiserfs_warning("not direntry %h\n", ih); | |
2098 | + break; | |
2099 | + } | |
2100 | + copy_item_head(&tmp_ih, ih); | |
2101 | + | |
2102 | + /* we must have found item, that is item of this directory, */ | |
2103 | + RFALSE( COMP_SHORT_KEYS (&(ih->ih_key), &pos_key), | |
2104 | + "vs-9000: found item %h does not match to dir we readdir %K", | |
2105 | + ih, &pos_key); | |
2106 | + | |
2107 | + if (deh_offset(deh) <= DOT_DOT_OFFSET) { | |
2108 | + break; | |
2109 | + } | |
2110 | + | |
2111 | + /* look for the previous entry in the directory */ | |
2112 | + next_pos = deh_offset (deh) - 1; | |
2113 | + | |
2114 | + if (!de_visible (deh)) | |
2115 | + /* it is hidden entry */ | |
2116 | + continue; | |
2117 | + | |
2118 | + d_reclen = entry_length(bh, ih, entry_num); | |
2119 | + d_name = B_I_DEH_ENTRY_FILE_NAME (bh, ih, deh); | |
2120 | + d_off = deh_offset (deh); | |
2121 | + d_ino = deh_objectid (deh); | |
2122 | + | |
2123 | + if (!d_name[d_reclen - 1]) | |
2124 | + d_reclen = strlen (d_name); | |
2125 | + | |
2126 | + if (d_reclen > REISERFS_MAX_NAME(inode->i_sb->s_blocksize)){ | |
2127 | + /* too big to send back to VFS */ | |
2128 | + continue ; | |
2129 | + } | |
2130 | + | |
2131 | + /* Ignore the .reiserfs_priv entry */ | |
2132 | + if (reiserfs_xattrs (inode->i_sb) && | |
2133 | + !old_format_only(inode->i_sb) && | |
2134 | + deh_objectid (deh) == le32_to_cpu (INODE_PKEY(inode->i_sb->u.reiserfs_sb.priv_root->d_inode)->k_objectid)) | |
2135 | + continue; | |
2136 | + | |
2137 | + if (d_reclen <= 32) { | |
2138 | + local_buf = small_buf ; | |
2139 | + } else { | |
2140 | + local_buf = reiserfs_kmalloc(d_reclen, GFP_NOFS, inode->i_sb) ; | |
2141 | + if (!local_buf) { | |
2142 | + pathrelse (&path_to_entry); | |
2143 | + return -ENOMEM ; | |
2144 | + } | |
2145 | + if (item_moved (&tmp_ih, &path_to_entry)) { | |
2146 | + reiserfs_kfree(local_buf, d_reclen, inode->i_sb) ; | |
2147 | + | |
2148 | + /* sigh, must retry. Do this same offset again */ | |
2149 | + next_pos = d_off; | |
2150 | + goto research; | |
2151 | + } | |
2152 | + } | |
2153 | + | |
2154 | + // Note, that we copy name to user space via temporary | |
2155 | + // buffer (local_buf) because filldir will block if | |
2156 | + // user space buffer is swapped out. At that time | |
2157 | + // entry can move to somewhere else | |
2158 | + memcpy (local_buf, d_name, d_reclen); | |
2159 | + | |
2160 | + /* the filldir function might need to start transactions, | |
2161 | + * or do who knows what. Release the path now that we've | |
2162 | + * copied all the important stuff out of the deh | |
2163 | + */ | |
2164 | + pathrelse (&path_to_entry); | |
2165 | + | |
2166 | + if (filldir (dirent, local_buf, d_reclen, d_off, d_ino, | |
2167 | + DT_UNKNOWN) < 0) { | |
2168 | + if (local_buf != small_buf) { | |
2169 | + reiserfs_kfree(local_buf, d_reclen, inode->i_sb) ; | |
2170 | + } | |
2171 | + goto end; | |
2172 | + } | |
2173 | + if (local_buf != small_buf) { | |
2174 | + reiserfs_kfree(local_buf, d_reclen, inode->i_sb) ; | |
2175 | + } | |
2176 | + } /* while */ | |
2177 | + | |
2178 | +end: | |
2179 | + pathrelse (&path_to_entry); | |
2180 | + return 0; | |
2181 | +} | |
2182 | + | |
2183 | +/* | |
2184 | + * this could be done with dedicated readdir ops for the xattr files, | |
2185 | + * but I want to get something working asap | |
2186 | + * this is stolen from vfs_readdir | |
2187 | + * | |
2188 | + */ | |
2189 | +static | |
2190 | +int xattr_readdir(struct file *file, filldir_t filler, void *buf) | |
2191 | +{ | |
2192 | + struct inode *inode = file->f_dentry->d_inode; | |
2193 | + int res = -ENOTDIR; | |
2194 | + if (!file->f_op || !file->f_op->readdir) | |
2195 | + goto out; | |
2196 | + down(&inode->i_sem); | |
2197 | + down(&inode->i_zombie); | |
2198 | + res = -ENOENT; | |
2199 | + if (!IS_DEADDIR(inode)) { | |
2200 | + lock_kernel(); | |
2201 | + res = __xattr_readdir(file, buf, filler); | |
2202 | + unlock_kernel(); | |
2203 | + } | |
2204 | + up(&inode->i_zombie); | |
2205 | + up(&inode->i_sem); | |
2206 | +out: | |
2207 | + return res; | |
2208 | +} | |
2209 | + | |
2210 | + | |
2211 | +/* Internal operations on file data */ | |
2212 | +static inline void | |
2213 | +reiserfs_put_page(struct page *page) | |
2214 | +{ | |
2215 | + kunmap(page); | |
2216 | + page_cache_release(page); | |
2217 | +} | |
2218 | + | |
2219 | +static struct page * | |
2220 | +reiserfs_get_page(struct inode *dir, unsigned long n) | |
2221 | +{ | |
2222 | + struct address_space *mapping = dir->i_mapping; | |
2223 | + struct page *page; | |
2224 | + /* We can deadlock if we try to free dentries, | |
2225 | + and an unlink/rmdir has just occured - GFP_NOFS avoids this */ | |
2226 | + mapping->gfp_mask = GFP_NOFS; | |
2227 | + page = read_cache_page (mapping, n, | |
2228 | + (filler_t*)mapping->a_ops->readpage, NULL); | |
2229 | + if (!IS_ERR(page)) { | |
2230 | + wait_on_page(page); | |
2231 | + kmap(page); | |
2232 | + if (!Page_Uptodate(page)) | |
2233 | + goto fail; | |
2234 | +/* | |
2235 | + if (!PageChecked(page)) | |
2236 | + ext2_check_page(page); | |
2237 | +*/ | |
2238 | + if (PageError(page)) | |
2239 | + goto fail; | |
2240 | + } | |
2241 | + return page; | |
2242 | + | |
2243 | +fail: | |
2244 | + reiserfs_put_page(page); | |
2245 | + return ERR_PTR(-EIO); | |
2246 | +} | |
2247 | + | |
2248 | +static inline __u32 | |
2249 | +xattr_hash (const char *msg, int len) | |
2250 | +{ | |
2251 | + return csum_partial (msg, len, 0); | |
2252 | +} | |
2253 | + | |
2254 | + | |
2255 | + | |
2256 | +/* Cache handling */ | |
2257 | +#if 0 /* def CONFIG_REISERFS_FS_XATTR_SHARING */ | |
2258 | +static struct mb_cache *reiserfs_xattr_cache; | |
2259 | + | |
2260 | +static void | |
2261 | +xa_cache_free_entry (struct mb_cache_entry *ce) | |
2262 | +{ | |
2263 | + struct inode *inode; | |
2264 | + if (!ce) | |
2265 | + return; | |
2266 | + | |
2267 | + inode = (struct inode *)ce->e_block; | |
2268 | + if (inode) /* inode may not be set if this is called in an error case */ | |
2269 | + iput (inode); | |
2270 | +} | |
2271 | + | |
2272 | +static struct mb_cache_op reiserfs_xa_cache_ops = { | |
2273 | + xa_cache_free_entry | |
2274 | +}; | |
2275 | + | |
2276 | +int __init | |
2277 | +reiserfs_xattr_cache_init (void) | |
2278 | +{ | |
2279 | + reiserfs_xattr_cache = mb_cache_create ("reiser_xa_cache", | |
2280 | + &reiserfs_xa_cache_ops, | |
2281 | + sizeof (struct mb_cache_entry) + | |
2282 | + sizeof (struct mb_cache_entry_index), | |
2283 | + 1, 61); | |
2284 | + if (!reiserfs_xattr_cache) | |
2285 | + return -ENOMEM; | |
2286 | + | |
2287 | + return 0; | |
2288 | +} | |
2289 | + | |
2290 | +void | |
2291 | +reiserfs_xattr_cache_exit (void) | |
2292 | +{ | |
2293 | + if (reiserfs_xattr_cache) | |
2294 | + mb_cache_destroy (reiserfs_xattr_cache); | |
2295 | +} | |
2296 | + | |
2297 | +void | |
2298 | +reiserfs_xattr_cache_clear (kdev_t dev) | |
2299 | +{ | |
2300 | + if (reiserfs_xattr_cache) | |
2301 | + mb_cache_shrink (reiserfs_xattr_cache, dev); | |
2302 | +} | |
2303 | + | |
2304 | +static struct inode * | |
2305 | +xa_cache_lookup (struct inode *inode, __u32 hash) | |
2306 | +{ | |
2307 | + struct mb_cache_entry *ce; | |
2308 | + struct inode *xattr_inode; | |
2309 | + | |
2310 | + if (!reiserfs_xattr_cache) | |
2311 | + return NULL; | |
2312 | + | |
2313 | + ce = mb_cache_entry_find_first (reiserfs_xattr_cache, 0, | |
2314 | + inode->i_dev, hash); | |
2315 | + while (ce) { | |
2316 | + struct inode *xattr_inode = (struct inode *)ce->e_block; | |
2317 | + if (!xattr_inode) { | |
2318 | + ce = mb_cache_entry_find_next (ce, 0, inode->i_dev, hash); | |
2319 | + continue; | |
2320 | + } | |
2321 | + if (xattr_inode->i_uid == inode->i_uid && | |
2322 | + xattr_inode->i_gid == inode->i_gid) { | |
2323 | + break; | |
2324 | + } | |
2325 | + ce = mb_cache_entry_find_next (ce, 0, inode->i_dev, hash); | |
2326 | + } | |
2327 | + | |
2328 | + if (!ce) | |
2329 | + return NULL; | |
2330 | + | |
2331 | + xattr_inode = (struct inode *)ce->e_block; | |
2332 | + mb_cache_entry_release (ce); | |
2333 | + | |
2334 | + if (xattr_inode) | |
2335 | + return igrab (xattr_inode); | |
2336 | + else | |
2337 | + return NULL; | |
2338 | +} | |
2339 | + | |
2340 | +/* We don't actually care about the errors since if it's not inserted, | |
2341 | + * we clean up after ourselves.. and then xa_cache_lookup just fails causing | |
2342 | + * a lookup. Performance loss, not corruption. */ | |
2343 | +static int | |
2344 | +xa_cache_insert (struct inode *xattr_inode, __u32 hash) | |
2345 | +{ | |
2346 | + struct mb_cache_entry *ce; | |
2347 | + int error; | |
2348 | + struct inode *inode = igrab (xattr_inode); | |
2349 | + if (!reiserfs_xattr_cache) | |
2350 | + return 0; | |
2351 | + | |
2352 | + if (!inode) | |
2353 | + return -ENOENT; | |
2354 | + | |
2355 | + ce = mb_cache_entry_alloc (reiserfs_xattr_cache); | |
2356 | + if (!ce) | |
2357 | + return -ENOMEM; | |
2358 | + | |
2359 | + ce->e_block = 0; | |
2360 | + error = mb_cache_entry_insert (ce, xattr_inode->i_dev, | |
2361 | + (unsigned long)xattr_inode, &hash); | |
2362 | + if (error) { | |
2363 | + mb_cache_entry_free (ce); | |
2364 | + if (error == -EBUSY) | |
2365 | + error = 0; /* if it's already there, it's ok */ | |
2366 | + } else | |
2367 | + mb_cache_entry_release (ce); | |
2368 | + | |
2369 | + return error; | |
2370 | +} | |
2371 | + | |
2372 | +static void | |
2373 | +xa_cache_remove (struct inode *xattr_inode) | |
2374 | +{ | |
2375 | + struct mb_cache_entry *ce; | |
2376 | + if (!reiserfs_xattr_cache) | |
2377 | + return; | |
2378 | + | |
2379 | + ce = mb_cache_entry_get (reiserfs_xattr_cache, xattr_inode->i_dev, | |
2380 | + (unsigned long) xattr_inode); | |
2381 | + if (ce) | |
2382 | + mb_cache_entry_free (ce); | |
2383 | + | |
2384 | + /* we would do an iput() here, but cache_ops->free takes care of that */ | |
2385 | +} | |
2386 | + | |
2387 | +#else | |
2388 | +# define xa_cache_insert(inode, hash) while(0) {} | |
2389 | +# define xa_cache_lookup(inode, hash) (NULL) | |
2390 | +# define xa_cache_remove(inode) while(0) {} | |
2391 | +#endif | |
2392 | + | |
2393 | +/* Generic extended attribute operations that can be used by xa plugins */ | |
2394 | + | |
2395 | +/* | |
2396 | + * inode->i_sem: down | |
2397 | + */ | |
2398 | +int | |
2399 | +reiserfs_xattr_set (struct inode *inode, const char *name, const void *buffer, | |
2400 | + size_t buffer_size, int flags) | |
2401 | +{ | |
2402 | + int err = 0; | |
2403 | + struct file *fp; | |
2404 | + struct page *page; | |
2405 | + char *data; | |
2406 | + struct address_space *mapping; | |
2407 | + size_t file_pos = 0; | |
2408 | + size_t buffer_pos = 0; | |
2409 | + struct inode *xinode; | |
2410 | + struct iattr newattrs; | |
2411 | + __u32 xahash = 0; | |
2412 | +#if 0 /* def CONFIG_REISERFS_FS_XATTR_SHARING */ | |
2413 | + struct dentry *xafile; | |
2414 | + struct inode *link = NULL; | |
2415 | +#endif | |
2416 | + | |
2417 | + if (get_inode_sd_version (inode) == STAT_DATA_V1) | |
2418 | + return -EOPNOTSUPP; | |
2419 | + | |
2420 | + /* Empty xattrs are ok, they're just empty files, no hash */ | |
2421 | + if (buffer && buffer_size) | |
2422 | + xahash = xattr_hash (buffer, buffer_size); | |
2423 | + | |
2424 | +#if 0 /* def CONFIG_REISERFS_FS_XATTR_SHARING */ | |
2425 | + link = xa_cache_lookup (inode, xahash); | |
2426 | + xafile = get_xa_file_dentry (inode, name, FL_READONLY); | |
2427 | + | |
2428 | + if (IS_ERR (xafile) && PTR_ERR (xafile) != -ENODATA) { | |
2429 | + if (link) | |
2430 | + iput (link); | |
2431 | + return PTR_ERR (xafile); | |
2432 | + } | |
2433 | + | |
2434 | + if (link) { /* Ok, we found a hit for the contents */ | |
2435 | + if (!IS_ERR (xafile) && xafile->d_inode && xafile->d_inode == link) { | |
2436 | + /* nothing to do, we're not changing the contents */ | |
2437 | + iput (link); | |
2438 | + dput (xafile); | |
2439 | + return 0; | |
2440 | + } else if (!IS_ERR (xafile) && xafile->d_inode) { | |
2441 | + /* unlink the old file, since we're linking to a new one */ | |
2442 | + err = reiserfs_xattr_del (inode, name); | |
2443 | + if (err) { | |
2444 | + iput (link); | |
2445 | + dput (xafile); | |
2446 | + return err; | |
2447 | + } | |
2448 | + } | |
2449 | + dput (xafile); | |
2450 | + err = reiserfs_xattr_link_to_inode (link, inode, name); | |
2451 | + iput (link); | |
2452 | + return err; | |
2453 | + } | |
2454 | +#endif | |
2455 | + | |
2456 | +open_file: | |
2457 | + fp = open_xa_file (inode, name, flags); | |
2458 | + if (IS_ERR (fp)) { | |
2459 | + err = PTR_ERR (fp); | |
2460 | + goto out; | |
2461 | + } | |
2462 | + | |
2463 | + xinode = fp->f_dentry->d_inode; | |
2464 | + | |
2465 | + /* we need to copy it off.. */ | |
2466 | + if (xinode->i_nlink > 1) { | |
2467 | + fput(fp); | |
2468 | + err = reiserfs_xattr_del (inode, name); | |
2469 | + if (err < 0) | |
2470 | + goto out; | |
2471 | + /* We just killed the old one, we're not replacing anymore */ | |
2472 | + if (flags & XATTR_REPLACE) | |
2473 | + flags &= ~XATTR_REPLACE; | |
2474 | + goto open_file; | |
2475 | + } | |
2476 | + | |
2477 | + /* Resize it so we're ok to write there */ | |
2478 | + newattrs.ia_size = buffer_size; | |
2479 | + newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME; | |
2480 | + down (&xinode->i_sem); | |
2481 | + err = notify_change(fp->f_dentry, &newattrs); | |
2482 | + if (err) | |
2483 | + goto out_filp; | |
2484 | + | |
2485 | + mapping = xinode->i_mapping; | |
2486 | + while (buffer_pos < buffer_size || buffer_pos == 0) { | |
2487 | + size_t chunk; | |
2488 | + size_t skip = 0; | |
2489 | + size_t page_offset = (file_pos & (PAGE_CACHE_SIZE - 1)); | |
2490 | + if (buffer_size - buffer_pos > PAGE_CACHE_SIZE) | |
2491 | + chunk = PAGE_CACHE_SIZE; | |
2492 | + else | |
2493 | + chunk = buffer_size - buffer_pos; | |
2494 | + | |
2495 | + page = reiserfs_get_page (xinode, file_pos >> PAGE_CACHE_SHIFT); | |
2496 | + if (IS_ERR (page)) { | |
2497 | + err = PTR_ERR (page); | |
2498 | + goto out_filp; | |
2499 | + } | |
2500 | + | |
2501 | + lock_page (page); | |
2502 | + data = page_address (page); | |
2503 | + | |
2504 | + if (file_pos == 0) { | |
2505 | + struct reiserfs_xattr_header *rxh; | |
2506 | + skip = file_pos = sizeof (struct reiserfs_xattr_header); | |
2507 | + if (chunk + skip > PAGE_CACHE_SIZE) | |
2508 | + chunk = PAGE_CACHE_SIZE - skip; | |
2509 | + rxh = (struct reiserfs_xattr_header *)data; | |
2510 | + rxh->h_magic = cpu_to_le32 (REISERFS_XATTR_MAGIC); | |
2511 | + rxh->h_hash = cpu_to_le32 (xahash); | |
2512 | + } | |
2513 | + | |
2514 | + err = mapping->a_ops->prepare_write (fp, page, page_offset, | |
2515 | + page_offset + chunk + skip); | |
2516 | + if (!err) { | |
2517 | + if (buffer) | |
2518 | + memcpy (data + skip, buffer + buffer_pos, chunk); | |
2519 | + err = mapping->a_ops->commit_write (fp, page, page_offset, | |
2520 | + page_offset + chunk + skip); | |
2521 | + } | |
2522 | + UnlockPage (page); | |
2523 | + reiserfs_put_page (page); | |
2524 | + buffer_pos += chunk; | |
2525 | + file_pos += chunk; | |
2526 | + skip = 0; | |
2527 | + if (err || buffer_size == 0 || !buffer) | |
2528 | + break; | |
2529 | + } | |
2530 | + | |
2531 | +out_filp: | |
2532 | + up (&xinode->i_sem); | |
2533 | + xa_cache_insert (xinode, xahash); | |
2534 | + fput(fp); | |
2535 | + | |
2536 | +out: | |
2537 | + return err; | |
2538 | +} | |
2539 | + | |
2540 | +/* | |
2541 | + * inode->i_sem: down | |
2542 | + */ | |
2543 | +int | |
2544 | +reiserfs_xattr_get (const struct inode *inode, const char *name, void *buffer, | |
2545 | + size_t buffer_size) | |
2546 | +{ | |
2547 | + ssize_t err = 0; | |
2548 | + struct file *fp; | |
2549 | + size_t isize; | |
2550 | + size_t file_pos = 0; | |
2551 | + size_t buffer_pos = 0; | |
2552 | + struct page *page; | |
2553 | + struct inode *xinode; | |
2554 | + __u32 hash = 0; | |
2555 | + | |
2556 | + /* We can't have xattrs attached to v1 items since they don't have | |
2557 | + * generation numbers */ | |
2558 | + if (get_inode_sd_version (inode) == STAT_DATA_V1) | |
2559 | + return -EOPNOTSUPP; | |
2560 | + | |
2561 | + fp = open_xa_file (inode, name, FL_READONLY); | |
2562 | + if (IS_ERR (fp)) { | |
2563 | + err = PTR_ERR (fp); | |
2564 | + goto out; | |
2565 | + } | |
2566 | + | |
2567 | + xinode = fp->f_dentry->d_inode; | |
2568 | + isize = xinode->i_size; | |
2569 | + | |
2570 | + /* Just return the size needed */ | |
2571 | + if (buffer == NULL) { | |
2572 | + err = isize - sizeof (struct reiserfs_xattr_header); | |
2573 | + goto out_dput; | |
2574 | + } | |
2575 | + | |
2576 | + if (buffer_size < isize - sizeof (struct reiserfs_xattr_header)) { | |
2577 | + err = -ERANGE; | |
2578 | + goto out_dput; | |
2579 | + } | |
2580 | + | |
2581 | + while (file_pos < isize) { | |
2582 | + size_t chunk; | |
2583 | + char *data; | |
2584 | + size_t page_offset; | |
2585 | + size_t skip = 0; | |
2586 | + if (isize - file_pos > PAGE_CACHE_SIZE) | |
2587 | + chunk = PAGE_CACHE_SIZE; | |
2588 | + else | |
2589 | + chunk = isize - file_pos; | |
2590 | + | |
2591 | + page = reiserfs_get_page (xinode, file_pos >> PAGE_CACHE_SHIFT); | |
2592 | + if (IS_ERR (page)) { | |
2593 | + err = PTR_ERR (page); | |
2594 | + goto out_dput; | |
2595 | + } | |
2596 | + | |
2597 | + lock_page (page); | |
2598 | + data = page_address (page); | |
2599 | + if (file_pos == 0) { | |
2600 | + struct reiserfs_xattr_header *rxh = | |
2601 | + (struct reiserfs_xattr_header *)data; | |
2602 | + skip = file_pos = sizeof (struct reiserfs_xattr_header); | |
2603 | + chunk -= skip; | |
2604 | + /* Magic doesn't match up.. */ | |
2605 | + if (rxh->h_magic != cpu_to_le32 (REISERFS_XATTR_MAGIC)) { | |
2606 | + UnlockPage (page); | |
2607 | + reiserfs_put_page (page); | |
2608 | + err = -EIO; | |
2609 | + goto out_dput; | |
2610 | + } | |
2611 | + hash = le32_to_cpu (rxh->h_hash); | |
2612 | + } | |
2613 | + memcpy (buffer + buffer_pos, data + skip, chunk); | |
2614 | + UnlockPage (page); | |
2615 | + reiserfs_put_page (page); | |
2616 | + file_pos += chunk; | |
2617 | + buffer_pos += chunk; | |
2618 | + skip = 0; | |
2619 | + } | |
2620 | + err = isize - sizeof (struct reiserfs_xattr_header); | |
2621 | + | |
2622 | + if (xattr_hash (buffer, isize - sizeof (struct reiserfs_xattr_header)) != hash) | |
2623 | + err = -EIO; | |
2624 | + | |
2625 | + /* Insert this inode into the xattr cache so we can attempt to do | |
2626 | + * decent sharing.. */ | |
2627 | + if (!err) | |
2628 | + xa_cache_insert (xinode, hash); | |
2629 | + | |
2630 | +out_dput: | |
2631 | + fput(fp); | |
2632 | + | |
2633 | +out: | |
2634 | + return err; | |
2635 | +} | |
2636 | + | |
2637 | +static int | |
2638 | +__reiserfs_xattr_del (struct dentry *xadir, const char *name, int namelen) | |
2639 | +{ | |
2640 | + struct dentry *file; | |
2641 | + struct inode *dir = xadir->d_inode; | |
2642 | + int err = 0; | |
2643 | + | |
2644 | + file = lookup_one_len (name, xadir, namelen); | |
2645 | + if (IS_ERR (file)) { | |
2646 | + err = PTR_ERR (file); | |
2647 | + goto out; | |
2648 | + } else if (!file->d_inode) { | |
2649 | + err = -ENODATA; | |
2650 | + goto out_file; | |
2651 | + } | |
2652 | + | |
2653 | + /* Skip directories.. */ | |
2654 | + if (S_ISDIR (file->d_inode->i_mode)) | |
2655 | + goto out_file; | |
2656 | + | |
2657 | + /* remove it from the xattr cache if this is the last reference to it */ | |
2658 | + if (file->d_inode->i_nlink <= 1) | |
2659 | + xa_cache_remove (file->d_inode); | |
2660 | + | |
2661 | + if (!is_reiserfs_priv_object (file->d_inode)) { | |
2662 | + reiserfs_warning ("trying to delete objectid %08x, which isn't an xattr!\n", le32_to_cpu (INODE_PKEY (file->d_inode)->k_objectid)); | |
2663 | + dput (file); | |
2664 | + return -EIO; | |
2665 | + } | |
2666 | + | |
2667 | + err = dir->i_op->unlink (dir, file); | |
2668 | + if (!err) | |
2669 | + d_delete (file); | |
2670 | + | |
2671 | +out_file: | |
2672 | + dput (file); | |
2673 | + | |
2674 | +out: | |
2675 | + return err; | |
2676 | +} | |
2677 | + | |
2678 | + | |
2679 | +int | |
2680 | +reiserfs_xattr_del (struct inode *inode, const char *name) | |
2681 | +{ | |
2682 | + struct dentry *dir; | |
2683 | + int err; | |
2684 | + | |
2685 | + dir = open_xa_dir (inode, FL_READONLY); | |
2686 | + if (IS_ERR (dir)) { | |
2687 | + err = PTR_ERR (dir); | |
2688 | + goto out; | |
2689 | + } | |
2690 | + | |
2691 | + err = __reiserfs_xattr_del (dir, name, strlen (name)); | |
2692 | + dput (dir); | |
2693 | + | |
2694 | +out: | |
2695 | + return err; | |
2696 | +} | |
2697 | + | |
2698 | +#if 0 /* def CONFIG_REISERFS_FS_XATTR_SHARING */ | |
2699 | +static int | |
2700 | +reiserfs_xattr_link_to_inode (struct inode *xattr_inode, | |
2701 | + struct inode *dst_inode, const char *dst_name) | |
2702 | +{ | |
2703 | + struct dentry *dst_dentry, *xadir; | |
2704 | + int err; | |
2705 | + | |
2706 | + xadir = open_xa_dir (dst_inode, 0); | |
2707 | + if (IS_ERR (xadir)) | |
2708 | + return PTR_ERR (xadir); | |
2709 | + | |
2710 | + dst_dentry = get_xa_file_dentry (dst_inode, dst_name, FL_READONLY); | |
2711 | + if (IS_ERR (dst_dentry)) { | |
2712 | + dput (xadir); | |
2713 | + } else if (dst_dentry->d_inode) { | |
2714 | + err = -EEXIST; | |
2715 | + goto out; | |
2716 | + } | |
2717 | + | |
2718 | + err = __reiserfs_link (xattr_inode, xadir->d_inode, dst_dentry); | |
2719 | + | |
2720 | +out: | |
2721 | + dput (dst_dentry); | |
2722 | + dput (xadir); | |
2723 | + return err; | |
2724 | +} | |
2725 | + | |
2726 | +int | |
2727 | +reiserfs_xattr_link (struct inode *src_inode, const char *src_name, | |
2728 | + struct inode *dst_inode, const char *dst_name) | |
2729 | +{ | |
2730 | + struct dentry *src_dentry; | |
2731 | + int err; | |
2732 | + | |
2733 | + src_dentry = get_xa_file_dentry (src_inode, src_name, FL_READONLY); | |
2734 | + if (IS_ERR (src_dentry)) { | |
2735 | + return PTR_ERR (src_dentry); | |
2736 | + } else if (!src_dentry->d_inode) { | |
2737 | + dput (src_dentry); | |
2738 | + return -ENODATA; | |
2739 | + } | |
2740 | + | |
2741 | + err = reiserfs_xattr_link_to_inode (src_dentry->d_inode, | |
2742 | + dst_inode, dst_name); | |
2743 | + dput (src_dentry); | |
2744 | + return err; | |
2745 | +} | |
2746 | +#endif | |
2747 | + | |
2748 | +/* The following are side effects of other operations that aren't explicitly | |
2749 | + * modifying extended attributes. This includes operations such as permissions | |
2750 | + * or ownership changes, object deletions, etc. */ | |
2751 | + | |
2752 | +static int | |
2753 | +reiserfs_delete_xattrs_filler (void *buf, const char *name, int namelen, | |
2754 | + loff_t offset, ino_t ino, unsigned int d_type) | |
2755 | +{ | |
2756 | + struct dentry *xadir = (struct dentry *)buf; | |
2757 | + | |
2758 | + return __reiserfs_xattr_del (xadir, name, namelen); | |
2759 | + | |
2760 | +} | |
2761 | + | |
2762 | +int | |
2763 | +reiserfs_delete_xattrs (struct inode *inode) | |
2764 | +{ | |
2765 | + struct file *fp; | |
2766 | + struct dentry *dir, *root; | |
2767 | + int err = 0; | |
2768 | + | |
2769 | + /* Skip out, an xattr has no xattrs associated with it */ | |
2770 | + if (is_reiserfs_priv_object (inode) || | |
2771 | + get_inode_sd_version (inode) == STAT_DATA_V1 || | |
2772 | + !reiserfs_xattrs(inode->i_sb)) | |
2773 | + { | |
2774 | + return 0; | |
2775 | + } | |
2776 | + reiserfs_read_lock_xattrs (inode->i_sb); | |
2777 | + dir = open_xa_dir (inode, FL_READONLY); | |
2778 | + reiserfs_read_unlock_xattrs (inode->i_sb); | |
2779 | + if (IS_ERR (dir)) { | |
2780 | + err = PTR_ERR (dir); | |
2781 | + goto out; | |
2782 | + } else if (!dir->d_inode) { | |
2783 | + dput (dir); | |
2784 | + return 0; | |
2785 | + } | |
2786 | + | |
2787 | + fp = dentry_open (dir, NULL, O_RDWR); | |
2788 | + if (IS_ERR (fp)) { | |
2789 | + err = PTR_ERR (fp); | |
2790 | + /* dentry_open dputs the dentry if it fails */ | |
2791 | + goto out; | |
2792 | + } | |
2793 | + | |
2794 | + lock_kernel (); | |
2795 | + err = xattr_readdir (fp, reiserfs_delete_xattrs_filler, dir); | |
2796 | + if (err) { | |
2797 | + unlock_kernel (); | |
2798 | + goto out_dir; | |
2799 | + } | |
2800 | + | |
2801 | + /* Leftovers besides . and .. -- that's not good. */ | |
2802 | + if (dir->d_inode->i_nlink <= 2) { | |
2803 | + root = get_xa_root (inode->i_sb); | |
2804 | + reiserfs_write_lock_xattrs (inode->i_sb); | |
2805 | + err = vfs_rmdir (root->d_inode, dir); | |
2806 | + reiserfs_write_unlock_xattrs (inode->i_sb); | |
2807 | + dput (root); | |
2808 | + } else { | |
2809 | + reiserfs_warning (inode->i_sb, "Couldn't remove all entries in directory\n"); | |
2810 | + } | |
2811 | + unlock_kernel (); | |
2812 | + | |
2813 | +out_dir: | |
2814 | + fput(fp); | |
2815 | + | |
2816 | +out: | |
2817 | + return err; | |
2818 | +} | |
2819 | + | |
2820 | +struct reiserfs_chown_buf { | |
2821 | + struct inode *inode; | |
2822 | + struct dentry *xadir; | |
2823 | + struct iattr *attrs; | |
2824 | +}; | |
2825 | + | |
2826 | +/* XXX: If there is a better way to do this, I'd love to hear about it */ | |
2827 | +static int | |
2828 | +reiserfs_chown_xattrs_filler (void *buf, const char *name, int namelen, | |
2829 | + loff_t offset, ino_t ino, unsigned int d_type) | |
2830 | +{ | |
2831 | + struct reiserfs_chown_buf *chown_buf = (struct reiserfs_chown_buf *)buf; | |
2832 | + struct dentry *xafile, *xadir = chown_buf->xadir; | |
2833 | + struct iattr *attrs = chown_buf->attrs; | |
2834 | + int err = 0; | |
2835 | + | |
2836 | + xafile = lookup_one_len (name, xadir, namelen); | |
2837 | + if (IS_ERR (xafile)) | |
2838 | + return PTR_ERR (xafile); | |
2839 | + else if (!xafile->d_inode) { | |
2840 | + dput (xafile); | |
2841 | + return -ENODATA; | |
2842 | + } | |
2843 | + | |
2844 | +#if 0 | |
2845 | + /* In this case we need to duplicate the file, since we're changing | |
2846 | + * the ownership of a shared file */ | |
2847 | + if (!S_ISDIR (xafile->d_inode->i_mode) && xafile->d_inode->i_nlink > 1) { | |
2848 | + struct inode *inode = chown_buf->inode; | |
2849 | + char *value; | |
2850 | + int ret, size; | |
2851 | + char namebuf[32]; | |
2852 | + char *nameptr; | |
2853 | + | |
2854 | + if (namelen > 31) | |
2855 | + nameptr = reiserfs_kmalloc (namelen+1, GFP_NOFS, inode->i_sb); | |
2856 | + else | |
2857 | + nameptr = namebuf; | |
2858 | + | |
2859 | + memcpy (nameptr, name, namelen); | |
2860 | + nameptr[namelen] = 0; | |
2861 | + size = reiserfs_xattr_get (inode, nameptr, NULL, 0); | |
2862 | + if (size < 0) { | |
2863 | + if (nameptr != namebuf) | |
2864 | + reiserfs_kfree (nameptr, namelen, inode->i_sb); | |
2865 | + dput (xafile); | |
2866 | + return size; | |
2867 | + } | |
2868 | + | |
2869 | + value = reiserfs_kmalloc (size, GFP_NOFS, inode->i_sb); | |
2870 | + if (!value) { | |
2871 | + if (nameptr != namebuf) | |
2872 | + reiserfs_kfree (nameptr, namelen, inode->i_sb); | |
2873 | + dput (xafile); | |
2874 | + return -ENOMEM; | |
2875 | + } | |
2876 | + | |
2877 | + ret = reiserfs_xattr_get (inode, nameptr, value, size); | |
2878 | + if (ret < 0) { | |
2879 | + if (nameptr != namebuf) | |
2880 | + reiserfs_kfree (nameptr, namelen, inode->i_sb); | |
2881 | + reiserfs_kfree (value, size, inode->i_sb); | |
2882 | + dput (xafile); | |
2883 | + return ret; | |
2884 | + } | |
2885 | + | |
2886 | + ret = reiserfs_xattr_del (inode, nameptr); | |
2887 | + dput (xafile); | |
2888 | + | |
2889 | + if (ret < 0) { | |
2890 | + if (nameptr != namebuf) | |
2891 | + reiserfs_kfree (nameptr, namelen, inode->i_sb); | |
2892 | + reiserfs_kfree (value, size, inode->i_sb); | |
2893 | + return ret; | |
2894 | + } | |
2895 | + | |
2896 | + ret = reiserfs_xattr_set (inode, nameptr, value, size, FL_DIR_SEM_HELD); | |
2897 | + reiserfs_kfree (value, size, inode->i_sb); | |
2898 | + | |
2899 | + if (nameptr != namebuf) | |
2900 | + reiserfs_kfree (nameptr, namelen, inode->i_sb); | |
2901 | + | |
2902 | + if (ret < 0) | |
2903 | + return ret; | |
2904 | + | |
2905 | + xafile = lookup_one_len (nameptr, xadir, namelen); | |
2906 | + if (IS_ERR (xafile)) | |
2907 | + return PTR_ERR (xafile); | |
2908 | + else if (!xafile->d_inode) { | |
2909 | + dput (xafile); | |
2910 | + return -ENODATA; | |
2911 | + } | |
2912 | + } | |
2913 | +#endif | |
2914 | + | |
2915 | + if (!S_ISDIR (xafile->d_inode->i_mode)) | |
2916 | + err = notify_change (xafile, attrs); | |
2917 | + dput (xafile); | |
2918 | + | |
2919 | + return err; | |
2920 | +} | |
2921 | + | |
2922 | +int | |
2923 | +reiserfs_chown_xattrs (struct inode *inode, struct iattr *attrs) | |
2924 | +{ | |
2925 | + struct file *fp; | |
2926 | + struct dentry *dir; | |
2927 | + int err = 0; | |
2928 | + struct reiserfs_chown_buf buf; | |
2929 | + unsigned int ia_valid = attrs->ia_valid; | |
2930 | + | |
2931 | + /* Skip out, an xattr has no xattrs associated with it */ | |
2932 | + if (is_reiserfs_priv_object (inode) || | |
2933 | + get_inode_sd_version (inode) == STAT_DATA_V1 || | |
2934 | + !reiserfs_xattrs(inode->i_sb)) | |
2935 | + { | |
2936 | + return 0; | |
2937 | + } | |
2938 | + reiserfs_read_lock_xattrs (inode->i_sb); | |
2939 | + dir = open_xa_dir (inode, FL_READONLY); | |
2940 | + reiserfs_read_unlock_xattrs (inode->i_sb); | |
2941 | + if (IS_ERR (dir)) { | |
2942 | + if (PTR_ERR (dir) != -ENODATA) | |
2943 | + err = PTR_ERR (dir); | |
2944 | + goto out; | |
2945 | + } else if (!dir->d_inode) { | |
2946 | + dput (dir); | |
2947 | + goto out; | |
2948 | + } | |
2949 | + | |
2950 | + fp = dentry_open (dir, NULL, O_RDWR); | |
2951 | + if (IS_ERR (fp)) { | |
2952 | + err = PTR_ERR (fp); | |
2953 | + /* dentry_open dputs the dentry if it fails */ | |
2954 | + goto out; | |
2955 | + } | |
2956 | + | |
2957 | + lock_kernel (); | |
2958 | + | |
2959 | + attrs->ia_valid &= (ATTR_UID | ATTR_GID | ATTR_CTIME); | |
2960 | + buf.xadir = dir; | |
2961 | + buf.attrs = attrs; | |
2962 | + buf.inode = inode; | |
2963 | + | |
2964 | + err = xattr_readdir (fp, reiserfs_chown_xattrs_filler, &buf); | |
2965 | + if (err) { | |
2966 | + unlock_kernel (); | |
2967 | + goto out_dir; | |
2968 | + } | |
2969 | + | |
2970 | + err = notify_change (dir, attrs); | |
2971 | + unlock_kernel (); | |
2972 | + | |
2973 | +out_dir: | |
2974 | + fput(fp); | |
2975 | + | |
2976 | +out: | |
2977 | + attrs->ia_valid = ia_valid; | |
2978 | + return err; | |
2979 | +} | |
2980 | + | |
2981 | + | |
2982 | +/* Actual operations that are exported to VFS-land */ | |
2983 | + | |
2984 | +/* | |
2985 | + * Inode operation getxattr() | |
2986 | + * dentry->d_inode->i_sem down | |
2987 | + * BKL held [before 2.5.x] | |
2988 | + */ | |
2989 | +ssize_t | |
2990 | +reiserfs_getxattr (struct dentry *dentry, const char *name, void *buffer, | |
2991 | + size_t size) | |
2992 | +{ | |
2993 | + struct reiserfs_xattr_handler *xah = find_xattr_handler_prefix (name); | |
2994 | + int err; | |
2995 | + | |
2996 | + if (!xah || !reiserfs_xattrs(dentry->d_sb) || | |
2997 | + get_inode_sd_version (dentry->d_inode) == STAT_DATA_V1) | |
2998 | + return -EOPNOTSUPP; | |
2999 | + | |
3000 | + reiserfs_read_lock_xattrs (dentry->d_sb); | |
3001 | + down(&dentry->d_inode->i_sem); | |
3002 | + err = xah->get (dentry->d_inode, name, buffer, size); | |
3003 | + up(&dentry->d_inode->i_sem); | |
3004 | + reiserfs_read_unlock_xattrs (dentry->d_sb); | |
3005 | + return err; | |
3006 | +} | |
3007 | + | |
3008 | + | |
3009 | +/* | |
3010 | + * Inode operation setxattr() | |
3011 | + * | |
3012 | + * dentry->d_inode->i_sem down | |
3013 | + * BKL held [before 2.5.x] | |
3014 | + */ | |
3015 | +int | |
3016 | +reiserfs_setxattr (struct dentry *dentry, const char *name, const void *value, | |
3017 | + size_t size, int flags) | |
3018 | +{ | |
3019 | + struct reiserfs_xattr_handler *xah = find_xattr_handler_prefix (name); | |
3020 | + int err; | |
3021 | + | |
3022 | + if (!xah || !reiserfs_xattrs(dentry->d_sb) || | |
3023 | + get_inode_sd_version (dentry->d_inode) == STAT_DATA_V1) | |
3024 | + return -EOPNOTSUPP; | |
3025 | + | |
3026 | + | |
3027 | + reiserfs_write_lock_xattrs (dentry->d_sb); | |
3028 | + err = xah->set (dentry->d_inode, name, value, size, flags); | |
3029 | + reiserfs_write_unlock_xattrs (dentry->d_sb); | |
3030 | + | |
3031 | + dentry->d_inode->i_ctime = CURRENT_TIME; | |
3032 | + mark_inode_dirty (dentry->d_inode); | |
3033 | + | |
3034 | + return err; | |
3035 | +} | |
3036 | + | |
3037 | +/* | |
3038 | + * Inode operation removexattr() | |
3039 | + * | |
3040 | + * dentry->d_inode->i_sem down | |
3041 | + * BKL held [before 2.5.x] | |
3042 | + */ | |
3043 | +int | |
3044 | +reiserfs_removexattr (struct dentry *dentry, const char *name) | |
3045 | +{ | |
3046 | + int err; | |
3047 | + struct reiserfs_xattr_handler *xah = find_xattr_handler_prefix (name); | |
3048 | + | |
3049 | + if (!xah || !reiserfs_xattrs(dentry->d_sb) || | |
3050 | + get_inode_sd_version (dentry->d_inode) == STAT_DATA_V1) | |
3051 | + return -EOPNOTSUPP; | |
3052 | + | |
3053 | + down (&dentry->d_inode->i_zombie); | |
3054 | + reiserfs_read_lock_xattrs (dentry->d_sb); | |
3055 | + | |
3056 | + /* Deletion pre-operation */ | |
3057 | + if (xah->del) { | |
3058 | + err = xah->del (dentry->d_inode, name); | |
3059 | + if (err) { | |
3060 | + reiserfs_read_unlock_xattrs (dentry->d_sb); | |
3061 | + up (&dentry->d_inode->i_zombie); | |
3062 | + return err; | |
3063 | + } | |
3064 | + } | |
3065 | + | |
3066 | + err = reiserfs_xattr_del (dentry->d_inode, name); | |
3067 | + reiserfs_read_unlock_xattrs (dentry->d_sb); | |
3068 | + up (&dentry->d_inode->i_zombie); | |
3069 | + | |
3070 | + dentry->d_inode->i_ctime = CURRENT_TIME; | |
3071 | + mark_inode_dirty (dentry->d_inode); | |
3072 | + return err; | |
3073 | +} | |
3074 | + | |
3075 | + | |
3076 | +/* This is what filldir will use: | |
3077 | + * r_pos will always contain the amount of space required for the entire | |
3078 | + * list. If r_pos becomes larger than r_size, we need more space and we | |
3079 | + * return an error indicating this. If r_pos is less than r_size, then we've | |
3080 | + * filled the buffer successfully and we return success */ | |
3081 | +struct reiserfs_listxattr_buf { | |
3082 | + int r_pos; | |
3083 | + int r_size; | |
3084 | + char *r_buf; | |
3085 | + struct inode *r_inode; | |
3086 | +}; | |
3087 | + | |
3088 | +static int | |
3089 | +reiserfs_listxattr_filler (void *buf, const char *name, int namelen, | |
3090 | + loff_t offset, ino_t ino, unsigned int d_type) | |
3091 | +{ | |
3092 | + struct reiserfs_listxattr_buf *b = (struct reiserfs_listxattr_buf *)buf; | |
3093 | + int len = 0; | |
3094 | + if (name[0] != '.' || (namelen != 1 && (name[1] != '.' || namelen != 2))) { | |
3095 | + struct reiserfs_xattr_handler *xah = find_xattr_handler_prefix (name); | |
3096 | + if (!xah) return 0; /* Unsupported xattr name, skip it */ | |
3097 | + | |
3098 | + /* We call ->list() twice because the operation isn't required to just | |
3099 | + * return the name back - we want to make sure we have enough space */ | |
3100 | + len += xah->list (b->r_inode, name, namelen, NULL); | |
3101 | + | |
3102 | + if (len) { | |
3103 | + if (b->r_pos + len + 1 <= b->r_size) { | |
3104 | + char *p = b->r_buf + b->r_pos; | |
3105 | + p += xah->list (b->r_inode, name, namelen, p); | |
3106 | + *p++ = '\0'; | |
3107 | + } | |
3108 | + b->r_pos += len + 1; | |
3109 | + } | |
3110 | + } | |
3111 | + | |
3112 | + return 0; | |
3113 | +} | |
3114 | + | |
3115 | +static ssize_t | |
3116 | +__reiserfs_listxattr (struct dentry *dentry, char *buffer, size_t size) | |
3117 | +{ | |
3118 | + struct file *fp; | |
3119 | + struct dentry *dir; | |
3120 | + int err = 0; | |
3121 | + struct reiserfs_listxattr_buf buf; | |
3122 | + | |
3123 | + if (!dentry->d_inode) | |
3124 | + return -EINVAL; | |
3125 | + | |
3126 | + if (!reiserfs_xattrs(dentry->d_sb) || | |
3127 | + get_inode_sd_version (dentry->d_inode) == STAT_DATA_V1) | |
3128 | + return -EOPNOTSUPP; | |
3129 | + | |
3130 | + reiserfs_read_lock_xattrs (dentry->d_sb); | |
3131 | + dir = open_xa_dir (dentry->d_inode, FL_READONLY); | |
3132 | + reiserfs_read_unlock_xattrs (dentry->d_sb); | |
3133 | + if (IS_ERR (dir)) { | |
3134 | + err = PTR_ERR (dir); | |
3135 | + if (err == -ENODATA) | |
3136 | + err = 0; /* Not an error if there aren't any xattrs */ | |
3137 | + goto out; | |
3138 | + } | |
3139 | + | |
3140 | + fp = dentry_open (dir, NULL, O_RDWR); | |
3141 | + if (IS_ERR (fp)) { | |
3142 | + err = PTR_ERR (fp); | |
3143 | + /* dentry_open dputs the dentry if it fails */ | |
3144 | + goto out; | |
3145 | + } | |
3146 | + | |
3147 | + buf.r_buf = buffer; | |
3148 | + buf.r_size = buffer ? size : 0; | |
3149 | + buf.r_pos = 0; | |
3150 | + buf.r_inode = dentry->d_inode; | |
3151 | + | |
3152 | + err = xattr_readdir (fp, reiserfs_listxattr_filler, &buf); | |
3153 | + if (err) | |
3154 | + goto out_dir; | |
3155 | + | |
3156 | + if (buf.r_pos > buf.r_size && buffer != NULL) | |
3157 | + err = -ERANGE; | |
3158 | + else | |
3159 | + err = buf.r_pos; | |
3160 | + | |
3161 | +out_dir: | |
3162 | + fput(fp); | |
3163 | + | |
3164 | +out: | |
3165 | + return err; | |
3166 | +} | |
3167 | + | |
3168 | +/* | |
3169 | + * Inode operation listxattr() | |
3170 | + * | |
3171 | + * dentry->d_inode->i_sem down | |
3172 | + * BKL held [before 2.5.x] | |
3173 | + */ | |
3174 | +ssize_t | |
3175 | +reiserfs_listxattr (struct dentry *dentry, char *buffer, size_t size) | |
3176 | +{ | |
3177 | + int error; | |
3178 | + | |
3179 | + down(&dentry->d_inode->i_sem); | |
3180 | + error = __reiserfs_listxattr(dentry, buffer, size); | |
3181 | + up(&dentry->d_inode->i_sem); | |
3182 | + | |
3183 | + return error; | |
3184 | +} | |
3185 | + | |
3186 | +/* This is the implementation for the xattr plugin infrastructure */ | |
3187 | +static struct reiserfs_xattr_handler *xattr_handlers; | |
3188 | +static rwlock_t handler_lock = RW_LOCK_UNLOCKED; | |
3189 | + | |
3190 | +static struct reiserfs_xattr_handler * | |
3191 | +find_xattr_handler_prefix (const char *prefix) | |
3192 | +{ | |
3193 | + struct reiserfs_xattr_handler **xah; | |
3194 | + read_lock (&handler_lock); | |
3195 | + for (xah = &xattr_handlers; *xah; xah=&(*xah)->next) | |
3196 | + if (strncmp ((*xah)->prefix, prefix, strlen ((*xah)->prefix)) == 0) | |
3197 | + break; | |
3198 | + read_unlock (&handler_lock); | |
3199 | + return *xah; | |
3200 | +} | |
3201 | + | |
3202 | +int | |
3203 | +reiserfs_xattr_register_handler (struct reiserfs_xattr_handler *handler) | |
3204 | +{ | |
3205 | + int res = 0; | |
3206 | + struct reiserfs_xattr_handler **xah; | |
3207 | + | |
3208 | + if (!handler) | |
3209 | + return -EINVAL; | |
3210 | + | |
3211 | + if (handler->next) | |
3212 | + return -EBUSY; | |
3213 | + | |
3214 | + write_lock (&handler_lock); | |
3215 | + | |
3216 | + for (xah = &xattr_handlers; *xah; xah=&(*xah)->next) { | |
3217 | + if (strcmp ((*xah)->prefix, handler->prefix) == 0) | |
3218 | + break; | |
3219 | + } | |
3220 | + if (*xah) | |
3221 | + res = -EBUSY; | |
3222 | + else | |
3223 | + *xah = handler; | |
3224 | + | |
3225 | + /* | |
3226 | + if (!res) | |
3227 | + printk ("ReiserFS: Registered xattr handler for %s\n", handler->prefix); | |
3228 | + */ | |
3229 | + | |
3230 | + write_unlock (&handler_lock); | |
3231 | + return res; | |
3232 | +} | |
3233 | + | |
3234 | +int | |
3235 | +reiserfs_xattr_unregister_handler (struct reiserfs_xattr_handler *handler) | |
3236 | +{ | |
3237 | + struct reiserfs_xattr_handler **xah; | |
3238 | + write_lock (&handler_lock); | |
3239 | + | |
3240 | + xah = &xattr_handlers; | |
3241 | + while (*xah) { | |
3242 | + if (handler == *xah) { | |
3243 | + *xah = handler->next; | |
3244 | + handler->next = NULL; | |
3245 | + write_unlock (&handler_lock); | |
3246 | + /* | |
3247 | + printk ("ReiserFS: Unregistered xattr handler for %s\n", | |
3248 | + handler->prefix); | |
3249 | + */ | |
3250 | + return 0; | |
3251 | + } | |
3252 | + xah = &(*xah)->next; | |
3253 | + } | |
3254 | + write_unlock (&handler_lock); | |
3255 | + return -EINVAL; | |
3256 | +} | |
3257 | + | |
3258 | + | |
3259 | +/* We need to take a copy of the mount flags since things like | |
3260 | + * MS_RDONLY don't get set until *after* we're called. | |
3261 | + * mount_flags != mount_options */ | |
3262 | +int | |
3263 | +reiserfs_xattr_init (struct super_block *s, int mount_flags) | |
3264 | +{ | |
3265 | + int err = 0; | |
3266 | + | |
3267 | + /* I hate using the _NO_ variant to clear bits. We use the normal variant | |
3268 | + * everywhere else, so just clear them both here */ | |
3269 | + if (test_bit (REISERFS_NO_XATTRS_USER, &(s->u.reiserfs_sb.s_mount_opt))) { | |
3270 | + clear_bit (REISERFS_XATTRS_USER, &(s->u.reiserfs_sb.s_mount_opt)); | |
3271 | + clear_bit (REISERFS_NO_XATTRS_USER, &(s->u.reiserfs_sb.s_mount_opt)); | |
3272 | + } | |
3273 | + | |
3274 | + if (test_bit (REISERFS_NO_POSIXACL, &(s->u.reiserfs_sb.s_mount_opt))) { | |
3275 | + clear_bit (REISERFS_POSIXACL, &(s->u.reiserfs_sb.s_mount_opt)); | |
3276 | + clear_bit (REISERFS_NO_POSIXACL, &(s->u.reiserfs_sb.s_mount_opt)); | |
3277 | + } | |
3278 | + | |
3279 | + | |
3280 | +#ifdef CONFIG_REISERFS_FS_XATTR_TRUSTED | |
3281 | + /* If we're a v3.6 filesystem, trusted xattrs are enabled across the board */ | |
3282 | + if (!old_format_only(s)) | |
3283 | + set_bit (REISERFS_XATTRS, &(s->u.reiserfs_sb.s_mount_opt)); | |
3284 | +#endif | |
3285 | + | |
3286 | + /* If the user has requested an optional xattrs type (e.g. user/acl), then | |
3287 | + * enable xattrs. If we're a v3.5 filesystem, this will get caught and | |
3288 | + * error out. If no optional xattrs are enabled, and trusted xattrs aren't | |
3289 | + * enabled, then disable xattrs */ | |
3290 | + if (reiserfs_xattrs_optional (s)) | |
3291 | + set_bit (REISERFS_XATTRS, &(s->u.reiserfs_sb.s_mount_opt)); | |
3292 | + else if (!reiserfs_xattrs_trusted (s)) | |
3293 | + clear_bit (REISERFS_XATTRS, &(s->u.reiserfs_sb.s_mount_opt)); | |
3294 | + | |
3295 | + if (reiserfs_xattrs (s)) { | |
3296 | + /* We need generation numbers to ensure that the oid mapping is correct | |
3297 | + * v3.5 filesystems don't have them. */ | |
3298 | + if (old_format_only (s)) { | |
3299 | + reiserfs_warning (s, "reiserfs: xattrs/ACLs not supported on pre v3.6 " | |
3300 | + "format filesystem. Failing mount.\n"); | |
3301 | + err = -EOPNOTSUPP; | |
3302 | + goto error; | |
3303 | + } else if (!s->u.reiserfs_sb.priv_root) { | |
3304 | + struct dentry *dentry = reiserfs_get_priv_root (s); | |
3305 | + if (!dentry && !(mount_flags & MS_RDONLY)) | |
3306 | + dentry = reiserfs_create_priv_root (s); | |
3307 | + if (!IS_ERR (dentry) && dentry) | |
3308 | + s->u.reiserfs_sb.priv_root = dentry; | |
3309 | + else { /* xattrs are unavailable */ | |
3310 | + /* If we're read-only it just means that the dir hasn't been | |
3311 | + * created. Not an error -- just no xattrs on the fs. We'll | |
3312 | + * check again if we go read-write */ | |
3313 | + if (!(mount_flags & MS_RDONLY)) { | |
3314 | + reiserfs_warning (s, "reiserfs: xattrs/ACLS enabled and couldn't " | |
3315 | + "find/create .reiserfs_priv. Failing mount.\n"); | |
3316 | + err = -EOPNOTSUPP; | |
3317 | + goto error; | |
3318 | + } | |
3319 | + /* Just to speed things up a bit since it won't find anything and | |
3320 | + * we're read-only */ | |
3321 | + clear_bit (REISERFS_XATTRS_USER, &(s->u.reiserfs_sb.s_mount_opt)); | |
3322 | + clear_bit (REISERFS_POSIXACL, &(s->u.reiserfs_sb.s_mount_opt)); | |
3323 | + } | |
3324 | + } /* otherwise, already mounted, and remounting */ | |
3325 | + } | |
3326 | + | |
3327 | + | |
3328 | +error: | |
3329 | + /* This is only nonzero if there was an error initializing the xattr | |
3330 | + * directory or if there is a condition where we don't support them. */ | |
3331 | + | |
3332 | + if (err) { | |
3333 | + clear_bit (REISERFS_XATTRS_USER, &(s->u.reiserfs_sb.s_mount_opt)); | |
3334 | + clear_bit (REISERFS_POSIXACL, &(s->u.reiserfs_sb.s_mount_opt)); | |
3335 | + clear_bit (REISERFS_XATTRS, &(s->u.reiserfs_sb.s_mount_opt)); | |
3336 | + } | |
3337 | + | |
3338 | + s->s_flags = (s->s_flags & ~MS_POSIXACL) | | |
3339 | + (reiserfs_posixacl (s) ? MS_POSIXACL : 0); | |
3340 | + return err; | |
3341 | +} | |
51560e02 AM |
3342 | diff -urN linux-2.4.22.org/fs/reiserfs/xattr_trusted.c linux-2.4.22/fs/reiserfs/xattr_trusted.c |
3343 | --- linux-2.4.22.org/fs/reiserfs/xattr_trusted.c 1970-01-01 01:00:00.000000000 +0100 | |
3344 | +++ linux-2.4.22/fs/reiserfs/xattr_trusted.c 2003-11-21 15:26:24.000000000 +0100 | |
e57e653a JR |
3345 | @@ -0,0 +1,97 @@ |
3346 | +#include <linux/reiserfs_fs.h> | |
3347 | +#include <linux/errno.h> | |
3348 | +#include <linux/fs.h> | |
3349 | +#include <linux/pagemap.h> | |
3350 | +#include <linux/xattr.h> | |
3351 | +#include <linux/reiserfs_xattr.h> | |
3352 | +#include <asm/uaccess.h> | |
3353 | + | |
3354 | +#ifdef CONFIG_REISERFS_FS_POSIX_ACL | |
3355 | +# include <linux/reiserfs_acl.h> | |
3356 | +#endif | |
3357 | + | |
3358 | +#define XATTR_TRUSTED_PREFIX "trusted." | |
3359 | + | |
3360 | +static int | |
3361 | +trusted_get (struct inode *inode, const char *name, void *buffer, size_t size) | |
3362 | +{ | |
3363 | + if (strlen(name) < sizeof(XATTR_TRUSTED_PREFIX)) | |
3364 | + return -EINVAL; | |
3365 | + | |
3366 | + if (!reiserfs_xattrs_trusted (inode->i_sb)) | |
3367 | + return -EOPNOTSUPP; | |
3368 | + | |
3369 | + if (!(capable(CAP_SYS_ADMIN) || is_reiserfs_priv_object(inode))) | |
3370 | + return -EPERM; | |
3371 | + | |
3372 | + return reiserfs_xattr_get (inode, name, buffer, size); | |
3373 | +} | |
3374 | + | |
3375 | +static int | |
3376 | +trusted_set (struct inode *inode, const char *name, const void *buffer, | |
3377 | + size_t size, int flags) | |
3378 | +{ | |
3379 | + if (strlen(name) < sizeof(XATTR_TRUSTED_PREFIX)) | |
3380 | + return -EINVAL; | |
3381 | + | |
3382 | + if (!reiserfs_xattrs_trusted (inode->i_sb)) | |
3383 | + return -EOPNOTSUPP; | |
3384 | + | |
3385 | + if (!(capable(CAP_SYS_ADMIN) || is_reiserfs_priv_object(inode))) | |
3386 | + return -EPERM; | |
3387 | + | |
3388 | + return reiserfs_xattr_set (inode, name, buffer, size, flags); | |
3389 | +} | |
3390 | + | |
3391 | +static int | |
3392 | +trusted_del (struct inode *inode, const char *name) | |
3393 | +{ | |
3394 | + if (strlen(name) < sizeof(XATTR_TRUSTED_PREFIX)) | |
3395 | + return -EINVAL; | |
3396 | + | |
3397 | + if (!reiserfs_xattrs_trusted (inode->i_sb)) | |
3398 | + return -EOPNOTSUPP; | |
3399 | + | |
3400 | + if (!(capable(CAP_SYS_ADMIN) || is_reiserfs_priv_object(inode))) | |
3401 | + return -EPERM; | |
3402 | + | |
3403 | + return 0; | |
3404 | +} | |
3405 | + | |
3406 | +static int | |
3407 | +trusted_list (struct inode *inode, const char *name, int namelen, char *out) | |
3408 | +{ | |
3409 | + int len = namelen; | |
3410 | + | |
3411 | + if (!reiserfs_xattrs_trusted (inode->i_sb)) | |
3412 | + return 0; | |
3413 | + | |
3414 | + if (!(capable(CAP_SYS_ADMIN) || is_reiserfs_priv_object(inode))) | |
3415 | + return 0; | |
3416 | + | |
3417 | + if (out) | |
3418 | + memcpy (out, name, len); | |
3419 | + | |
3420 | + return len; | |
3421 | +} | |
3422 | + | |
3423 | + | |
3424 | +struct reiserfs_xattr_handler trusted_handler = { | |
3425 | + prefix: XATTR_TRUSTED_PREFIX, | |
3426 | + get: trusted_get, | |
3427 | + set: trusted_set, | |
3428 | + del: trusted_del, | |
3429 | + list: trusted_list, | |
3430 | +}; | |
3431 | + | |
3432 | +int __init | |
3433 | +reiserfs_xattr_trusted_init (void) | |
3434 | +{ | |
3435 | + return reiserfs_xattr_register_handler (&trusted_handler); | |
3436 | +} | |
3437 | + | |
3438 | +int | |
3439 | +reiserfs_xattr_trusted_exit (void) | |
3440 | +{ | |
3441 | + return reiserfs_xattr_unregister_handler (&trusted_handler); | |
3442 | +} | |
51560e02 AM |
3443 | diff -urN linux-2.4.22.org/fs/reiserfs/xattr_user.c linux-2.4.22/fs/reiserfs/xattr_user.c |
3444 | --- linux-2.4.22.org/fs/reiserfs/xattr_user.c 1970-01-01 01:00:00.000000000 +0100 | |
3445 | +++ linux-2.4.22/fs/reiserfs/xattr_user.c 2003-11-21 15:26:24.000000000 +0100 | |
e57e653a JR |
3446 | @@ -0,0 +1,112 @@ |
3447 | +#include <linux/reiserfs_fs.h> | |
3448 | +#include <linux/errno.h> | |
3449 | +#include <linux/fs.h> | |
3450 | +#include <linux/pagemap.h> | |
3451 | +#include <linux/xattr.h> | |
3452 | +#include <linux/reiserfs_xattr.h> | |
3453 | +#include <asm/uaccess.h> | |
3454 | + | |
3455 | +#ifdef CONFIG_REISERFS_FS_POSIX_ACL | |
3456 | +# include <linux/reiserfs_acl.h> | |
3457 | +#endif | |
3458 | + | |
3459 | +#define XATTR_USER_PREFIX "user." | |
3460 | + | |
3461 | +static int | |
3462 | +user_get (struct inode *inode, const char *name, void *buffer, size_t size) | |
3463 | +{ | |
3464 | + | |
3465 | + int error; | |
3466 | + | |
3467 | + if (strlen(name) < sizeof(XATTR_USER_PREFIX)) | |
3468 | + return -EINVAL; | |
3469 | + | |
3470 | + if (!reiserfs_xattrs_user (inode->i_sb)) | |
3471 | + return -EOPNOTSUPP; | |
3472 | + | |
3473 | + error = reiserfs_permission_locked (inode, MAY_READ); | |
3474 | + if (error) | |
3475 | + return error; | |
3476 | + | |
3477 | + return reiserfs_xattr_get (inode, name, buffer, size); | |
3478 | +} | |
3479 | + | |
3480 | +static int | |
3481 | +user_set (struct inode *inode, const char *name, const void *buffer, | |
3482 | + size_t size, int flags) | |
3483 | +{ | |
3484 | + | |
3485 | + int error; | |
3486 | + | |
3487 | + if (strlen(name) < sizeof(XATTR_USER_PREFIX)) | |
3488 | + return -EINVAL; | |
3489 | + | |
3490 | + if (!reiserfs_xattrs_user (inode->i_sb)) | |
3491 | + return -EOPNOTSUPP; | |
3492 | + | |
3493 | + if (!S_ISREG (inode->i_mode) && | |
3494 | + (!S_ISDIR (inode->i_mode) || inode->i_mode & S_ISVTX)) | |
3495 | + return -EPERM; | |
3496 | + | |
3497 | + error = reiserfs_permission_locked (inode, MAY_WRITE); | |
3498 | + if (error) | |
3499 | + return error; | |
3500 | + | |
3501 | + return reiserfs_xattr_set (inode, name, buffer, size, flags); | |
3502 | +} | |
3503 | + | |
3504 | +static int | |
3505 | +user_del (struct inode *inode, const char *name) | |
3506 | +{ | |
3507 | + int error; | |
3508 | + | |
3509 | + if (strlen(name) < sizeof(XATTR_USER_PREFIX)) | |
3510 | + return -EINVAL; | |
3511 | + | |
3512 | + if (!reiserfs_xattrs_user (inode->i_sb)) | |
3513 | + return -EOPNOTSUPP; | |
3514 | + | |
3515 | + if (!S_ISREG (inode->i_mode) && | |
3516 | + (!S_ISDIR (inode->i_mode) || inode->i_mode & S_ISVTX)) | |
3517 | + return -EPERM; | |
3518 | + | |
3519 | + error = reiserfs_permission_locked (inode, MAY_WRITE); | |
3520 | + if (error) | |
3521 | + return error; | |
3522 | + | |
3523 | + return 0; | |
3524 | +} | |
3525 | + | |
3526 | +static int | |
3527 | +user_list (struct inode *inode, const char *name, int namelen, char *out) | |
3528 | +{ | |
3529 | + int len = namelen; | |
3530 | + if (!reiserfs_xattrs_user (inode->i_sb)) | |
3531 | + return 0; | |
3532 | + | |
3533 | + if (out) | |
3534 | + memcpy (out, name, len); | |
3535 | + | |
3536 | + return len; | |
3537 | +} | |
3538 | + | |
3539 | + | |
3540 | +struct reiserfs_xattr_handler user_handler = { | |
3541 | + prefix: XATTR_USER_PREFIX, | |
3542 | + get: user_get, | |
3543 | + set: user_set, | |
3544 | + del: user_del, | |
3545 | + list: user_list, | |
3546 | +}; | |
3547 | + | |
3548 | +int __init | |
3549 | +reiserfs_xattr_user_init (void) | |
3550 | +{ | |
3551 | + return reiserfs_xattr_register_handler (&user_handler); | |
3552 | +} | |
3553 | + | |
3554 | +int | |
3555 | +reiserfs_xattr_user_exit (void) | |
3556 | +{ | |
3557 | + return reiserfs_xattr_unregister_handler (&user_handler); | |
3558 | +} | |
51560e02 AM |
3559 | diff -urN linux-2.4.22.org/include/asm-i386/bugs.h linux-2.4.22/include/asm-i386/bugs.h |
3560 | --- linux-2.4.22.org/include/asm-i386/bugs.h 2002-08-03 02:39:45.000000000 +0200 | |
3561 | +++ linux-2.4.22/include/asm-i386/bugs.h 2003-11-21 15:26:24.000000000 +0100 | |
e57e653a JR |
3562 | @@ -200,6 +200,11 @@ |
3563 | && (boot_cpu_data.x86_mask < 6 || boot_cpu_data.x86_mask == 11)) | |
3564 | panic("Kernel compiled for PMMX+, assumes a local APIC without the read-before-write bug!"); | |
3565 | #endif | |
3566 | + | |
3567 | +#ifdef CONFIG_X86_CMPXCHG8 | |
3568 | + if (!cpu_has_cx8) | |
3569 | + panic("Kernel compiled for Pentium+, requires CMPXCHG8B feature!"); | |
3570 | +#endif | |
3571 | } | |
3572 | ||
3573 | static void __init check_bugs(void) | |
51560e02 AM |
3574 | diff -urN linux-2.4.22.org/include/asm-i386/cpufeature.h linux-2.4.22/include/asm-i386/cpufeature.h |
3575 | --- linux-2.4.22.org/include/asm-i386/cpufeature.h 2003-11-21 15:04:19.000000000 +0100 | |
3576 | +++ linux-2.4.22/include/asm-i386/cpufeature.h 2003-11-21 15:27:01.000000000 +0100 | |
3577 | @@ -89,6 +89,7 @@ | |
e57e653a | 3578 | #define cpu_has_pge boot_cpu_has(X86_FEATURE_PGE) |
51560e02 | 3579 | #define cpu_has_sse2 boot_cpu_has(X86_FEATURE_XMM2) |
e57e653a | 3580 | #define cpu_has_apic boot_cpu_has(X86_FEATURE_APIC) |
51560e02 AM |
3581 | +#define cpu_has_cx8 boot_cpu_has(X86_FEATURE_CX8) |
3582 | #define cpu_has_sep boot_cpu_has(X86_FEATURE_SEP) | |
e57e653a JR |
3583 | #define cpu_has_mtrr boot_cpu_has(X86_FEATURE_MTRR) |
3584 | #define cpu_has_mmx boot_cpu_has(X86_FEATURE_MMX) | |
51560e02 AM |
3585 | diff -urN linux-2.4.22.org/include/asm-i386/system.h linux-2.4.22/include/asm-i386/system.h |
3586 | --- linux-2.4.22.org/include/asm-i386/system.h 2003-11-21 15:04:24.000000000 +0100 | |
3587 | +++ linux-2.4.22/include/asm-i386/system.h 2003-11-21 15:26:24.000000000 +0100 | |
e57e653a JR |
3588 | @@ -143,6 +143,8 @@ |
3589 | #define __xg(x) ((struct __xchg_dummy *)(x)) | |
3590 | ||
3591 | ||
3592 | +#ifdef CONFIG_X86_CMPXCHG8 | |
3593 | +#define __ARCH_HAS_GET_SET_64BIT 1 | |
3594 | /* | |
3595 | * The semantics of XCHGCMP8B are a bit strange, this is why | |
3596 | * there is a loop and the loading of %%eax and %%edx has to | |
3597 | @@ -167,7 +169,7 @@ | |
3598 | "lock cmpxchg8b (%0)\n\t" | |
3599 | "jnz 1b" | |
3600 | : /* no outputs */ | |
3601 | - : "D"(ptr), | |
3602 | + : "r"(ptr), | |
3603 | "b"(low), | |
3604 | "c"(high) | |
3605 | : "ax","dx","memory"); | |
3606 | @@ -197,6 +199,32 @@ | |
3607 | __set_64bit(ptr, (unsigned int)(value), (unsigned int)((value)>>32ULL) ) : \ | |
3608 | __set_64bit(ptr, ll_low(value), ll_high(value)) ) | |
3609 | ||
3610 | + | |
3611 | +/* | |
3612 | + * The memory clobber is needed in the read side only if | |
3613 | + * there is an unsafe writer before the get_64bit, which should | |
3614 | + * never be the case, but just to be safe. | |
3615 | + */ | |
3616 | +static inline unsigned long long get_64bit(unsigned long long * ptr) | |
3617 | +{ | |
3618 | + unsigned long low, high; | |
3619 | + | |
3620 | + __asm__ __volatile__ ( | |
3621 | + "\n1:\t" | |
3622 | + "movl (%2), %%eax\n\t" | |
3623 | + "movl 4(%2), %%edx\n\t" | |
3624 | + "movl %%eax, %%ebx\n\t" | |
3625 | + "movl %%edx, %%ecx\n\t" | |
3626 | + "lock cmpxchg8b (%2)\n\t" | |
3627 | + "jnz 1b" | |
3628 | + : "=&b" (low), "=&c" (high) | |
3629 | + : "r" (ptr) | |
3630 | + : "ax","dx","memory"); | |
3631 | + | |
3632 | + return low | ((unsigned long long) high << 32); | |
3633 | +} | |
3634 | +#endif /* CONFIG_X86_CMPXCHG */ | |
3635 | + | |
3636 | /* | |
3637 | * Note: no "lock" prefix even on SMP: xchg always implies lock anyway | |
3638 | * Note 2: xchg has side effect, so that attribute volatile is necessary, | |
51560e02 AM |
3639 | diff -urN linux-2.4.22.org/include/linux/fs.h linux-2.4.22/include/linux/fs.h |
3640 | --- linux-2.4.22.org/include/linux/fs.h 2003-11-21 15:14:25.000000000 +0100 | |
3641 | +++ linux-2.4.22/include/linux/fs.h 2003-11-21 15:26:24.000000000 +0100 | |
3642 | @@ -441,6 +441,13 @@ | |
e57e653a JR |
3643 | struct list_head bd_inodes; |
3644 | }; | |
3645 | ||
3646 | +#if BITS_PER_LONG==32 && defined(CONFIG_SMP) && !defined(__ARCH_HAS_GET_SET_64BIT) | |
3647 | +#define __NEED_I_SIZE_ORDERED | |
3648 | +#define i_size_ordered_init(inode) do { (inode)->i_size_version1 = (inode)->i_size_version2 = 0; } while (0) | |
3649 | +#else | |
3650 | +#define i_size_ordered_init(inode) do { } while (0) | |
3651 | +#endif | |
3652 | + | |
3653 | struct inode { | |
3654 | struct list_head i_hash; | |
3655 | struct list_head i_list; | |
51560e02 AM |
3656 | @@ -527,8 +534,65 @@ |
3657 | struct jffs2_inode_info jffs2_i; | |
e57e653a JR |
3658 | void *generic_ip; |
3659 | } u; | |
3660 | +#ifdef __NEED_I_SIZE_ORDERED | |
3661 | + volatile int i_size_version1; | |
3662 | + volatile int i_size_version2; | |
3663 | +#endif | |
3664 | }; | |
3665 | ||
3666 | +/* | |
3667 | + * NOTE: in a 32bit arch with a preemptable kernel and | |
3668 | + * an UP compile the i_size_read/write must be atomic | |
3669 | + * with respect to the local cpu (unlike with preempt disabled), | |
3670 | + * but they don't need to be atomic with respect to other cpus like in | |
3671 | + * true SMP (so they need either to either locally disable irq around | |
3672 | + * the read or for example on x86 they can be still implemented as a | |
3673 | + * cmpxchg8b without the need of the lock prefix). For SMP compiles | |
3674 | + * and 64bit archs it makes no difference if preempt is enabled or not. | |
3675 | + */ | |
3676 | +static inline loff_t i_size_read(struct inode * inode) | |
3677 | +{ | |
3678 | +#if BITS_PER_LONG==32 && defined(CONFIG_SMP) | |
3679 | +#ifdef __ARCH_HAS_GET_SET_64BIT | |
3680 | + return (loff_t) get_64bit((unsigned long long *) &inode->i_size); | |
3681 | +#else | |
3682 | + loff_t i_size; | |
3683 | + int v1, v2; | |
3684 | + | |
3685 | + /* Retry if i_size was possibly modified while sampling. */ | |
3686 | + do { | |
3687 | + v1 = inode->i_size_version1; | |
3688 | + rmb(); | |
3689 | + i_size = inode->i_size; | |
3690 | + rmb(); | |
3691 | + v2 = inode->i_size_version2; | |
3692 | + } while (v1 != v2); | |
3693 | + | |
3694 | + return i_size; | |
3695 | +#endif | |
3696 | +#elif BITS_PER_LONG==64 || !defined(CONFIG_SMP) | |
3697 | + return inode->i_size; | |
3698 | +#endif | |
3699 | +} | |
3700 | + | |
3701 | +static inline void i_size_write(struct inode * inode, loff_t i_size) | |
3702 | +{ | |
3703 | +#if BITS_PER_LONG==32 && defined(CONFIG_SMP) | |
3704 | +#ifdef __ARCH_HAS_GET_SET_64BIT | |
3705 | + set_64bit((unsigned long long *) &inode->i_size, (unsigned long long) i_size); | |
3706 | +#else | |
3707 | + inode->i_size_version2++; | |
3708 | + wmb(); | |
3709 | + inode->i_size = i_size; | |
3710 | + wmb(); | |
3711 | + inode->i_size_version1++; | |
3712 | + wmb(); /* make it visible ASAP */ | |
3713 | +#endif | |
3714 | +#elif BITS_PER_LONG==64 || !defined(CONFIG_SMP) | |
3715 | + inode->i_size = i_size; | |
3716 | +#endif | |
3717 | +} | |
3718 | + | |
3719 | static inline void inode_add_bytes(struct inode *inode, loff_t bytes) | |
3720 | { | |
3721 | inode->i_blocks += bytes >> 9; | |
51560e02 | 3722 | @@ -824,6 +888,7 @@ |
e57e653a JR |
3723 | extern int vfs_mknod(struct inode *, struct dentry *, int, dev_t); |
3724 | extern int vfs_symlink(struct inode *, struct dentry *, const char *); | |
3725 | extern int vfs_link(struct dentry *, struct inode *, struct dentry *); | |
3726 | +extern int __vfs_rmdir(struct inode *, struct dentry *); | |
3727 | extern int vfs_rmdir(struct inode *, struct dentry *); | |
3728 | extern int vfs_unlink(struct inode *, struct dentry *); | |
3729 | extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *); | |
51560e02 | 3730 | @@ -1402,6 +1467,7 @@ |
e57e653a JR |
3731 | extern int follow_down(struct vfsmount **, struct dentry **); |
3732 | extern int follow_up(struct vfsmount **, struct dentry **); | |
3733 | extern struct dentry * lookup_one_len(const char *, struct dentry *, int); | |
3734 | +extern struct dentry * __lookup_hash(struct qstr *, struct dentry *); | |
3735 | extern struct dentry * lookup_hash(struct qstr *, struct dentry *); | |
3736 | #define user_path_walk(name,nd) __user_walk(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd) | |
3737 | #define user_path_walk_link(name,nd) __user_walk(name, LOOKUP_POSITIVE, nd) | |
51560e02 AM |
3738 | diff -urN linux-2.4.22.org/include/linux/reiserfs_acl.h linux-2.4.22/include/linux/reiserfs_acl.h |
3739 | --- linux-2.4.22.org/include/linux/reiserfs_acl.h 1970-01-01 01:00:00.000000000 +0100 | |
3740 | +++ linux-2.4.22/include/linux/reiserfs_acl.h 2003-11-21 15:26:24.000000000 +0100 | |
e57e653a JR |
3741 | @@ -0,0 +1,92 @@ |
3742 | +#include <linux/init.h> | |
3743 | +#include <linux/posix_acl.h> | |
3744 | +#include <linux/xattr_acl.h> | |
3745 | + | |
3746 | +#define REISERFS_ACL_VERSION 0x0001 | |
3747 | + | |
3748 | +typedef struct { | |
3749 | + __u16 e_tag; | |
3750 | + __u16 e_perm; | |
3751 | + __u32 e_id; | |
3752 | +} reiserfs_acl_entry; | |
3753 | + | |
3754 | +typedef struct { | |
3755 | + __u16 e_tag; | |
3756 | + __u16 e_perm; | |
3757 | +} reiserfs_acl_entry_short; | |
3758 | + | |
3759 | +typedef struct { | |
3760 | + __u32 a_version; | |
3761 | +} reiserfs_acl_header; | |
3762 | + | |
3763 | +static inline size_t reiserfs_acl_size(int count) | |
3764 | +{ | |
3765 | + if (count <= 4) { | |
3766 | + return sizeof(reiserfs_acl_header) + | |
3767 | + count * sizeof(reiserfs_acl_entry_short); | |
3768 | + } else { | |
3769 | + return sizeof(reiserfs_acl_header) + | |
3770 | + 4 * sizeof(reiserfs_acl_entry_short) + | |
3771 | + (count - 4) * sizeof(reiserfs_acl_entry); | |
3772 | + } | |
3773 | +} | |
3774 | + | |
3775 | +static inline int reiserfs_acl_count(size_t size) | |
3776 | +{ | |
3777 | + ssize_t s; | |
3778 | + size -= sizeof(reiserfs_acl_header); | |
3779 | + s = size - 4 * sizeof(reiserfs_acl_entry_short); | |
3780 | + if (s < 0) { | |
3781 | + if (size % sizeof(reiserfs_acl_entry_short)) | |
3782 | + return -1; | |
3783 | + return size / sizeof(reiserfs_acl_entry_short); | |
3784 | + } else { | |
3785 | + if (s % sizeof(reiserfs_acl_entry)) | |
3786 | + return -1; | |
3787 | + return s / sizeof(reiserfs_acl_entry) + 4; | |
3788 | + } | |
3789 | +} | |
3790 | + | |
3791 | + | |
3792 | +#ifdef CONFIG_REISERFS_FS_POSIX_ACL | |
3793 | +struct posix_acl * reiserfs_get_acl(struct inode *inode, int type); | |
3794 | +int reiserfs_set_acl(struct inode *inode, int type, struct posix_acl *acl); | |
3795 | +int reiserfs_permission (struct inode *inode, int mask); | |
3796 | +int reiserfs_permission_locked (struct inode *inode, int mask); | |
3797 | +int reiserfs_acl_chmod (struct inode *inode); | |
3798 | +int reiserfs_inherit_default_acl (struct inode *dir, struct dentry *dentry, struct inode *inode); | |
3799 | +int reiserfs_cache_default_acl (struct inode *dir); | |
3800 | +extern int reiserfs_xattr_posix_acl_init (void) __init; | |
3801 | +extern int reiserfs_xattr_posix_acl_exit (void); | |
3802 | +#else | |
3803 | + | |
3804 | +#define reiserfs_permission NULL | |
3805 | +#define reiserfs_set_acl NULL | |
3806 | +#define reiserfs_get_acl NULL | |
3807 | +#define reiserfs_cache_default_acl(inode) 0 | |
3808 | + | |
3809 | +static inline int | |
3810 | +reiserfs_xattr_posix_acl_init (void) | |
3811 | +{ | |
3812 | + return 0; | |
3813 | +} | |
3814 | + | |
3815 | +static inline int | |
3816 | +reiserfs_xattr_posix_acl_exit (void) | |
3817 | +{ | |
3818 | + return 0; | |
3819 | +} | |
3820 | + | |
3821 | +static inline int | |
3822 | +reiserfs_acl_chmod (struct inode *inode) | |
3823 | +{ | |
3824 | + return 0; | |
3825 | +} | |
3826 | + | |
3827 | +static inline int | |
3828 | +reiserfs_inherit_default_acl (const struct inode *dir, struct dentry *dentry, struct inode *inode) | |
3829 | +{ | |
3830 | + return 0; | |
3831 | +} | |
3832 | + | |
3833 | +#endif | |
51560e02 AM |
3834 | diff -urN linux-2.4.22.org/include/linux/reiserfs_fs.h linux-2.4.22/include/linux/reiserfs_fs.h |
3835 | --- linux-2.4.22.org/include/linux/reiserfs_fs.h 2003-11-21 15:14:25.000000000 +0100 | |
3836 | +++ linux-2.4.22/include/linux/reiserfs_fs.h 2003-11-21 15:26:24.000000000 +0100 | |
e57e653a JR |
3837 | @@ -2007,17 +2007,23 @@ |
3838 | static inline void reiserfs_update_sd(struct reiserfs_transaction_handle *th, | |
3839 | struct inode *inode) | |
3840 | { | |
3841 | - reiserfs_update_sd_size(th, inode, inode->i_size) ; | |
3842 | + reiserfs_update_sd_size(th, inode, i_size_read(inode)) ; | |
3843 | } | |
3844 | ||
3845 | void sd_attrs_to_i_attrs( __u16 sd_attrs, struct inode *inode ); | |
3846 | void i_attrs_to_sd_attrs( struct inode *inode, __u16 *sd_attrs ); | |
3847 | +int reiserfs_setattr(struct dentry *dentry, struct iattr *attr); | |
3848 | ||
3849 | /* namei.c */ | |
3850 | inline void set_de_name_and_namelen (struct reiserfs_dir_entry * de); | |
3851 | int search_by_entry_key (struct super_block * sb, const struct cpu_key * key, | |
3852 | struct path * path, | |
3853 | struct reiserfs_dir_entry * de); | |
3854 | +int __reiserfs_link (struct inode *inode, struct inode *dir, struct dentry *dentry); | |
3855 | +int reiserfs_find_entry (struct inode * dir, const char * name, int namelen, | |
3856 | + struct path * path_to_entry, | |
3857 | + struct reiserfs_dir_entry * de); | |
3858 | + | |
3859 | /* procfs.c */ | |
3860 | ||
3861 | #if defined( CONFIG_PROC_FS ) && defined( CONFIG_REISERFS_PROC_INFO ) | |
3862 | @@ -2081,6 +2087,7 @@ | |
3863 | ||
3864 | /* dir.c */ | |
3865 | extern struct inode_operations reiserfs_dir_inode_operations; | |
3866 | +extern struct inode_operations reiserfs_symlink_inode_operations; | |
3867 | extern struct file_operations reiserfs_dir_operations; | |
3868 | ||
3869 | /* tail_conversion.c */ | |
3870 | @@ -2301,6 +2308,9 @@ | |
3871 | #define REISERFS_IOC_GETVERSION EXT2_IOC_GETVERSION | |
3872 | #define REISERFS_IOC_SETVERSION EXT2_IOC_SETVERSION | |
3873 | ||
3874 | +/* xattr stuff */ | |
3875 | +#define REISERFS_XATTR_DIR_SEM(s) ((s)->u.reiserfs_sb.xattr_dir_sem) | |
3876 | + | |
3877 | #endif /* _LINUX_REISER_FS_H */ | |
3878 | ||
3879 | ||
51560e02 AM |
3880 | diff -urN linux-2.4.22.org/include/linux/reiserfs_fs_i.h linux-2.4.22/include/linux/reiserfs_fs_i.h |
3881 | --- linux-2.4.22.org/include/linux/reiserfs_fs_i.h 2003-11-21 15:14:25.000000000 +0100 | |
3882 | +++ linux-2.4.22/include/linux/reiserfs_fs_i.h 2003-11-21 15:26:24.000000000 +0100 | |
e57e653a JR |
3883 | @@ -28,6 +28,7 @@ |
3884 | i_link_saved_truncate_mask = 0x0020, | |
3885 | /** are we logging data blocks for this file? */ | |
3886 | i_data_log = 0x0040, | |
3887 | + i_priv_object = 0x0080, | |
3888 | } reiserfs_inode_flags; | |
3889 | ||
3890 | ||
3891 | @@ -64,6 +65,9 @@ | |
3892 | */ | |
3893 | unsigned long i_tail_trans_id; | |
3894 | struct reiserfs_journal_list *i_tail_jl; | |
3895 | + | |
3896 | + struct posix_acl *i_acl_access; | |
3897 | + struct posix_acl *i_acl_default; | |
3898 | }; | |
3899 | ||
3900 | #endif | |
51560e02 AM |
3901 | diff -urN linux-2.4.22.org/include/linux/reiserfs_fs_sb.h linux-2.4.22/include/linux/reiserfs_fs_sb.h |
3902 | --- linux-2.4.22.org/include/linux/reiserfs_fs_sb.h 2003-11-21 15:14:25.000000000 +0100 | |
3903 | +++ linux-2.4.22/include/linux/reiserfs_fs_sb.h 2003-11-21 15:26:24.000000000 +0100 | |
e57e653a JR |
3904 | @@ -6,6 +6,7 @@ |
3905 | ||
3906 | #ifdef __KERNEL__ | |
3907 | #include <linux/tqueue.h> | |
3908 | +#include <linux/rwsem.h> | |
3909 | #endif | |
3910 | ||
3911 | // | |
3912 | @@ -442,6 +443,9 @@ | |
3913 | struct proc_dir_entry *procdir; | |
3914 | int reserved_blocks; /* amount of blocks reserved for further allocations */ | |
3915 | struct list_head s_reiserfs_supers; | |
3916 | + struct dentry *priv_root; /* root of /.reiserfs_priv */ | |
3917 | + struct dentry *xattr_root; /* root of /.reiserfs_priv/.xa */ | |
3918 | + struct rw_semaphore xattr_dir_sem; | |
3919 | }; | |
3920 | ||
3921 | /* Definitions of reiserfs on-disk properties: */ | |
3922 | @@ -486,6 +490,11 @@ | |
3923 | REISERFS_DATA_WRITEBACK, | |
3924 | REISERFS_ATTRS, | |
3925 | REISERFS_TEST4, | |
3926 | + REISERFS_XATTRS, | |
3927 | + REISERFS_XATTRS_USER, | |
3928 | + REISERFS_POSIXACL, | |
3929 | + REISERFS_NO_XATTRS_USER, | |
3930 | + REISERFS_NO_POSIXACL, | |
3931 | }; | |
3932 | ||
3933 | #define reiserfs_r5_hash(s) ((s)->u.reiserfs_sb.s_mount_opt & (1 << FORCE_R5_HASH)) | |
3934 | @@ -507,6 +516,15 @@ | |
3935 | #define reiserfs_attrs(s) ((s)->u.reiserfs_sb.s_mount_opt & (1 << REISERFS_ATTRS)) | |
3936 | #define old_format_only(s) ((s)->u.reiserfs_sb.s_properties & (1 << REISERFS_3_5)) | |
3937 | #define convert_reiserfs(s) ((s)->u.reiserfs_sb.s_mount_opt & (1 << REISERFS_CONVERT)) | |
3938 | +#define reiserfs_xattrs_user(s) ((s)->u.reiserfs_sb.s_mount_opt & (1 << REISERFS_XATTRS_USER)) | |
3939 | +#define reiserfs_posixacl(s) ((s)->u.reiserfs_sb.s_mount_opt & (1 << REISERFS_POSIXACL)) | |
3940 | +#define reiserfs_xattrs_optional(s) (reiserfs_xattrs_user(s) || reiserfs_posixacl(s)) | |
3941 | +#define reiserfs_xattrs(s) ((s)->u.reiserfs_sb.s_mount_opt & (1 << REISERFS_XATTRS)) | |
3942 | +#ifdef CONFIG_REISERFS_FS_XATTR_TRUSTED | |
3943 | +# define reiserfs_xattrs_trusted(s) reiserfs_xattrs(s) | |
3944 | +#else | |
3945 | +# define reiserfs_xattrs_trusted(s) (0) | |
3946 | +#endif | |
3947 | ||
3948 | ||
3949 | void reiserfs_file_buffer (struct buffer_head * bh, int list); | |
51560e02 AM |
3950 | diff -urN linux-2.4.22.org/include/linux/reiserfs_xattr.h linux-2.4.22/include/linux/reiserfs_xattr.h |
3951 | --- linux-2.4.22.org/include/linux/reiserfs_xattr.h 1970-01-01 01:00:00.000000000 +0100 | |
3952 | +++ linux-2.4.22/include/linux/reiserfs_xattr.h 2003-11-21 15:26:24.000000000 +0100 | |
e57e653a JR |
3953 | @@ -0,0 +1,155 @@ |
3954 | +/* | |
3955 | + File: linux/reiserfs_xattr.h | |
3956 | +*/ | |
3957 | + | |
3958 | +#include <linux/config.h> | |
3959 | +#include <linux/init.h> | |
3960 | +#include <linux/xattr.h> | |
3961 | + | |
3962 | +/* Magic value in header */ | |
3963 | +#define REISERFS_XATTR_MAGIC 0x52465841 /* "RFXA" */ | |
3964 | + | |
3965 | +struct reiserfs_xattr_header { | |
3966 | + __u32 h_magic; /* magic number for identification */ | |
3967 | + __u32 h_hash; /* hash of the value */ | |
3968 | +}; | |
3969 | + | |
3970 | +#ifdef __KERNEL__ | |
3971 | + | |
3972 | +struct reiserfs_xattr_handler { | |
3973 | + char *prefix; | |
3974 | + int (*get)(struct inode *inode, const char *name, void *buffer, | |
3975 | + size_t size); | |
3976 | + int (*set)(struct inode *inode, const char *name, const void *buffer, | |
3977 | + size_t size, int flags); | |
3978 | + int (*del)(struct inode *inode, const char *name); | |
3979 | + int (*list)(struct inode *inode, const char *name, int namelen, char *out); | |
3980 | + struct reiserfs_xattr_handler *next; | |
3981 | +}; | |
3982 | + | |
3983 | + | |
3984 | +#ifdef CONFIG_REISERFS_FS_XATTR | |
3985 | +#define is_reiserfs_priv_object(inode) (((inode)->u.reiserfs_i.i_flags & i_priv_object) == i_priv_object) | |
3986 | +ssize_t reiserfs_getxattr (struct dentry *dentry, const char *name, | |
3987 | + void *buffer, size_t size); | |
3988 | +int reiserfs_setxattr (struct dentry *dentry, const char *name, | |
3989 | + const void *value, size_t size, int flags); | |
3990 | +ssize_t reiserfs_listxattr (struct dentry *dentry, char *buffer, size_t size); | |
3991 | +int reiserfs_removexattr (struct dentry *dentry, const char *name); | |
3992 | +int reiserfs_delete_xattrs (struct inode *inode); | |
3993 | +int reiserfs_chown_xattrs (struct inode *inode, struct iattr *attrs); | |
3994 | +int reiserfs_xattr_init (struct super_block *sb, int mount_flags); | |
3995 | + | |
3996 | +static inline void | |
3997 | +reiserfs_write_lock_xattrs(struct super_block *sb) | |
3998 | +{ | |
3999 | + down_write (&REISERFS_XATTR_DIR_SEM(sb)); | |
4000 | +} | |
4001 | +static inline void | |
4002 | +reiserfs_write_unlock_xattrs(struct super_block *sb) | |
4003 | +{ | |
4004 | + up_write (&REISERFS_XATTR_DIR_SEM(sb)); | |
4005 | +} | |
4006 | +static inline void | |
4007 | +reiserfs_read_lock_xattrs(struct super_block *sb) | |
4008 | +{ | |
4009 | + down_read (&REISERFS_XATTR_DIR_SEM(sb)); | |
4010 | +} | |
4011 | +static inline void | |
4012 | +reiserfs_read_unlock_xattrs(struct super_block *sb) | |
4013 | +{ | |
4014 | + up_read (&REISERFS_XATTR_DIR_SEM(sb)); | |
4015 | +} | |
4016 | +#else | |
4017 | +#define is_reiserfs_priv_object(inode) 0 | |
4018 | +#define reiserfs_getxattr NULL | |
4019 | +#define reiserfs_setxattr NULL | |
4020 | +#define reiserfs_listxattr NULL | |
4021 | +#define reiserfs_removexattr NULL | |
4022 | +#define reiserfs_write_lock_xattrs(sb) | |
4023 | +#define reiserfs_write_unlock_xattrs(sb) | |
4024 | +#define reiserfs_read_lock_xattrs(sb) | |
4025 | +#define reiserfs_read_unlock_xattrs(sb) | |
4026 | +static inline int | |
4027 | +reiserfs_xattr_init (struct super_block *s, int mount_flags) | |
4028 | +{ | |
4029 | + s->s_flags = (s->s_flags & ~MS_POSIXACL); /* to be sure */ | |
4030 | + return 0; | |
4031 | +} | |
4032 | + | |
4033 | +static inline int | |
4034 | +reiserfs_delete_xattrs (struct inode *inode) | |
4035 | +{ | |
4036 | + return 0; | |
4037 | +} | |
4038 | + | |
4039 | +static inline int | |
4040 | +reiserfs_chown_xattrs (struct inode *inode, struct iattr *attrs) | |
4041 | +{ | |
4042 | + return 0; | |
4043 | +} | |
4044 | +#endif | |
4045 | + | |
4046 | +extern int reiserfs_xattr_register_handler(struct reiserfs_xattr_handler *); | |
4047 | +extern int reiserfs_xattr_unregister_handler(struct reiserfs_xattr_handler *); | |
4048 | +extern int reiserfs_xattr_del (struct inode *, const char *); | |
4049 | +extern int reiserfs_xattr_get (const struct inode *, const char *, void *, size_t); | |
4050 | +extern int reiserfs_xattr_set (struct inode *, const char *, const void *, | |
4051 | + size_t, int); | |
4052 | + | |
4053 | +#if 0 /* def CONFIG_REISERFS_FS_XATTR_SHARING */ | |
4054 | +int reiserfs_xattr_cache_init (void) __init; | |
4055 | +void reiserfs_xattr_cache_exit (void); | |
4056 | +void reiserfs_xattr_cache_clear (kdev_t dev); | |
4057 | +#else | |
4058 | +static inline int | |
4059 | +reiserfs_xattr_cache_init (void) | |
4060 | +{ | |
4061 | + return 0; | |
4062 | +} | |
4063 | + | |
4064 | +static inline int | |
4065 | +reiserfs_xattr_cache_exit (void) | |
4066 | +{ | |
4067 | + return 0; | |
4068 | +} | |
4069 | + | |
4070 | +static inline void | |
4071 | +reiserfs_xattr_cache_clear (kdev_t dev) | |
4072 | +{ | |
4073 | +}; | |
4074 | +#endif | |
4075 | +#ifdef CONFIG_REISERFS_FS_XATTR_USER | |
4076 | +extern int reiserfs_xattr_user_init (void) __init; | |
4077 | +extern int reiserfs_xattr_user_exit (void); | |
4078 | +#else | |
4079 | +static inline int | |
4080 | +reiserfs_xattr_user_init (void) | |
4081 | +{ | |
4082 | + return 0; | |
4083 | +} | |
4084 | + | |
4085 | +static inline int | |
4086 | +reiserfs_xattr_user_exit (void) | |
4087 | +{ | |
4088 | + return 0; | |
4089 | +} | |
4090 | +#endif | |
4091 | +#ifdef CONFIG_REISERFS_FS_XATTR_TRUSTED | |
4092 | +extern int reiserfs_xattr_trusted_init (void) __init; | |
4093 | +extern int reiserfs_xattr_trusted_exit (void); | |
4094 | +#else | |
4095 | +static inline int | |
4096 | +reiserfs_xattr_trusted_init (void) | |
4097 | +{ | |
4098 | + return 0; | |
4099 | +} | |
4100 | + | |
4101 | +static inline int | |
4102 | +reiserfs_xattr_trusted_exit (void) | |
4103 | +{ | |
4104 | + return 0; | |
4105 | +} | |
4106 | +#endif | |
4107 | + | |
4108 | +#endif /* __KERNEL__ */ |