diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /fs/reiserfs/xattr.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'fs/reiserfs/xattr.c')
-rw-r--r-- | fs/reiserfs/xattr.c | 1450 |
1 files changed, 1450 insertions, 0 deletions
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c new file mode 100644 index 000000000000..45582fe8b466 --- /dev/null +++ b/fs/reiserfs/xattr.c | |||
@@ -0,0 +1,1450 @@ | |||
1 | /* | ||
2 | * linux/fs/reiserfs/xattr.c | ||
3 | * | ||
4 | * Copyright (c) 2002 by Jeff Mahoney, <jeffm@suse.com> | ||
5 | * | ||
6 | */ | ||
7 | |||
8 | /* | ||
9 | * In order to implement EA/ACLs in a clean, backwards compatible manner, | ||
10 | * they are implemented as files in a "private" directory. | ||
11 | * Each EA is in it's own file, with the directory layout like so (/ is assumed | ||
12 | * to be relative to fs root). Inside the /.reiserfs_priv/xattrs directory, | ||
13 | * directories named using the capital-hex form of the objectid and | ||
14 | * generation number are used. Inside each directory are individual files | ||
15 | * named with the name of the extended attribute. | ||
16 | * | ||
17 | * So, for objectid 12648430, we could have: | ||
18 | * /.reiserfs_priv/xattrs/C0FFEE.0/system.posix_acl_access | ||
19 | * /.reiserfs_priv/xattrs/C0FFEE.0/system.posix_acl_default | ||
20 | * /.reiserfs_priv/xattrs/C0FFEE.0/user.Content-Type | ||
21 | * .. or similar. | ||
22 | * | ||
23 | * The file contents are the text of the EA. The size is known based on the | ||
24 | * stat data describing the file. | ||
25 | * | ||
26 | * In the case of system.posix_acl_access and system.posix_acl_default, since | ||
27 | * these are special cases for filesystem ACLs, they are interpreted by the | ||
28 | * kernel, in addition, they are negatively and positively cached and attached | ||
29 | * to the inode so that unnecessary lookups are avoided. | ||
30 | */ | ||
31 | |||
32 | #include <linux/reiserfs_fs.h> | ||
33 | #include <linux/dcache.h> | ||
34 | #include <linux/namei.h> | ||
35 | #include <linux/errno.h> | ||
36 | #include <linux/fs.h> | ||
37 | #include <linux/file.h> | ||
38 | #include <linux/pagemap.h> | ||
39 | #include <linux/xattr.h> | ||
40 | #include <linux/reiserfs_xattr.h> | ||
41 | #include <linux/reiserfs_acl.h> | ||
42 | #include <linux/mbcache.h> | ||
43 | #include <asm/uaccess.h> | ||
44 | #include <asm/checksum.h> | ||
45 | #include <linux/smp_lock.h> | ||
46 | #include <linux/stat.h> | ||
47 | #include <asm/semaphore.h> | ||
48 | |||
49 | #define FL_READONLY 128 | ||
50 | #define FL_DIR_SEM_HELD 256 | ||
51 | #define PRIVROOT_NAME ".reiserfs_priv" | ||
52 | #define XAROOT_NAME "xattrs" | ||
53 | |||
54 | static struct reiserfs_xattr_handler *find_xattr_handler_prefix (const char *prefix); | ||
55 | |||
56 | static struct dentry * | ||
57 | create_xa_root (struct super_block *sb) | ||
58 | { | ||
59 | struct dentry *privroot = dget (REISERFS_SB(sb)->priv_root); | ||
60 | struct dentry *xaroot; | ||
61 | |||
62 | /* This needs to be created at mount-time */ | ||
63 | if (!privroot) | ||
64 | return ERR_PTR(-EOPNOTSUPP); | ||
65 | |||
66 | xaroot = lookup_one_len (XAROOT_NAME, privroot, strlen (XAROOT_NAME)); | ||
67 | if (IS_ERR (xaroot)) { | ||
68 | goto out; | ||
69 | } else if (!xaroot->d_inode) { | ||
70 | int err; | ||
71 | down (&privroot->d_inode->i_sem); | ||
72 | err = privroot->d_inode->i_op->mkdir (privroot->d_inode, xaroot, 0700); | ||
73 | up (&privroot->d_inode->i_sem); | ||
74 | |||
75 | if (err) { | ||
76 | dput (xaroot); | ||
77 | dput (privroot); | ||
78 | return ERR_PTR (err); | ||
79 | } | ||
80 | REISERFS_SB(sb)->xattr_root = dget (xaroot); | ||
81 | } | ||
82 | |||
83 | out: | ||
84 | dput (privroot); | ||
85 | return xaroot; | ||
86 | } | ||
87 | |||
88 | /* This will return a dentry, or error, refering to the xa root directory. | ||
89 | * If the xa root doesn't exist yet, the dentry will be returned without | ||
90 | * an associated inode. This dentry can be used with ->mkdir to create | ||
91 | * the xa directory. */ | ||
92 | static struct dentry * | ||
93 | __get_xa_root (struct super_block *s) | ||
94 | { | ||
95 | struct dentry *privroot = dget (REISERFS_SB(s)->priv_root); | ||
96 | struct dentry *xaroot = NULL; | ||
97 | |||
98 | if (IS_ERR (privroot) || !privroot) | ||
99 | return privroot; | ||
100 | |||
101 | xaroot = lookup_one_len (XAROOT_NAME, privroot, strlen (XAROOT_NAME)); | ||
102 | if (IS_ERR (xaroot)) { | ||
103 | goto out; | ||
104 | } else if (!xaroot->d_inode) { | ||
105 | dput (xaroot); | ||
106 | xaroot = NULL; | ||
107 | goto out; | ||
108 | } | ||
109 | |||
110 | REISERFS_SB(s)->xattr_root = dget (xaroot); | ||
111 | |||
112 | out: | ||
113 | dput (privroot); | ||
114 | return xaroot; | ||
115 | } | ||
116 | |||
117 | /* Returns the dentry (or NULL) referring to the root of the extended | ||
118 | * attribute directory tree. If it has already been retreived, it is used. | ||
119 | * Otherwise, we attempt to retreive it from disk. It may also return | ||
120 | * a pointer-encoded error. | ||
121 | */ | ||
122 | static inline struct dentry * | ||
123 | get_xa_root (struct super_block *s) | ||
124 | { | ||
125 | struct dentry *dentry = dget (REISERFS_SB(s)->xattr_root); | ||
126 | |||
127 | if (!dentry) | ||
128 | dentry = __get_xa_root (s); | ||
129 | |||
130 | return dentry; | ||
131 | } | ||
132 | |||
133 | /* Opens the directory corresponding to the inode's extended attribute store. | ||
134 | * If flags allow, the tree to the directory may be created. If creation is | ||
135 | * prohibited, -ENODATA is returned. */ | ||
136 | static struct dentry * | ||
137 | open_xa_dir (const struct inode *inode, int flags) | ||
138 | { | ||
139 | struct dentry *xaroot, *xadir; | ||
140 | char namebuf[17]; | ||
141 | |||
142 | xaroot = get_xa_root (inode->i_sb); | ||
143 | if (IS_ERR (xaroot)) { | ||
144 | return xaroot; | ||
145 | } else if (!xaroot) { | ||
146 | if (flags == 0 || flags & XATTR_CREATE) { | ||
147 | xaroot = create_xa_root (inode->i_sb); | ||
148 | if (IS_ERR (xaroot)) | ||
149 | return xaroot; | ||
150 | } | ||
151 | if (!xaroot) | ||
152 | return ERR_PTR (-ENODATA); | ||
153 | } | ||
154 | |||
155 | /* ok, we have xaroot open */ | ||
156 | |||
157 | snprintf (namebuf, sizeof (namebuf), "%X.%X", | ||
158 | le32_to_cpu (INODE_PKEY (inode)->k_objectid), | ||
159 | inode->i_generation); | ||
160 | xadir = lookup_one_len (namebuf, xaroot, strlen (namebuf)); | ||
161 | if (IS_ERR (xadir)) { | ||
162 | dput (xaroot); | ||
163 | return xadir; | ||
164 | } | ||
165 | |||
166 | if (!xadir->d_inode) { | ||
167 | int err; | ||
168 | if (flags == 0 || flags & XATTR_CREATE) { | ||
169 | /* Although there is nothing else trying to create this directory, | ||
170 | * another directory with the same hash may be created, so we need | ||
171 | * to protect against that */ | ||
172 | err = xaroot->d_inode->i_op->mkdir (xaroot->d_inode, xadir, 0700); | ||
173 | if (err) { | ||
174 | dput (xaroot); | ||
175 | dput (xadir); | ||
176 | return ERR_PTR (err); | ||
177 | } | ||
178 | } | ||
179 | if (!xadir->d_inode) { | ||
180 | dput (xaroot); | ||
181 | dput (xadir); | ||
182 | return ERR_PTR (-ENODATA); | ||
183 | } | ||
184 | } | ||
185 | |||
186 | dput (xaroot); | ||
187 | return xadir; | ||
188 | } | ||
189 | |||
190 | /* Returns a dentry corresponding to a specific extended attribute file | ||
191 | * for the inode. If flags allow, the file is created. Otherwise, a | ||
192 | * valid or negative dentry, or an error is returned. */ | ||
193 | static struct dentry * | ||
194 | get_xa_file_dentry (const struct inode *inode, const char *name, int flags) | ||
195 | { | ||
196 | struct dentry *xadir, *xafile; | ||
197 | int err = 0; | ||
198 | |||
199 | xadir = open_xa_dir (inode, flags); | ||
200 | if (IS_ERR (xadir)) { | ||
201 | return ERR_PTR (PTR_ERR (xadir)); | ||
202 | } else if (xadir && !xadir->d_inode) { | ||
203 | dput (xadir); | ||
204 | return ERR_PTR (-ENODATA); | ||
205 | } | ||
206 | |||
207 | xafile = lookup_one_len (name, xadir, strlen (name)); | ||
208 | if (IS_ERR (xafile)) { | ||
209 | dput (xadir); | ||
210 | return ERR_PTR (PTR_ERR (xafile)); | ||
211 | } | ||
212 | |||
213 | if (xafile->d_inode) { /* file exists */ | ||
214 | if (flags & XATTR_CREATE) { | ||
215 | err = -EEXIST; | ||
216 | dput (xafile); | ||
217 | goto out; | ||
218 | } | ||
219 | } else if (flags & XATTR_REPLACE || flags & FL_READONLY) { | ||
220 | goto out; | ||
221 | } else { | ||
222 | /* inode->i_sem is down, so nothing else can try to create | ||
223 | * the same xattr */ | ||
224 | err = xadir->d_inode->i_op->create (xadir->d_inode, xafile, | ||
225 | 0700|S_IFREG, NULL); | ||
226 | |||
227 | if (err) { | ||
228 | dput (xafile); | ||
229 | goto out; | ||
230 | } | ||
231 | } | ||
232 | |||
233 | out: | ||
234 | dput (xadir); | ||
235 | if (err) | ||
236 | xafile = ERR_PTR (err); | ||
237 | return xafile; | ||
238 | } | ||
239 | |||
240 | |||
241 | /* Opens a file pointer to the attribute associated with inode */ | ||
242 | static struct file * | ||
243 | open_xa_file (const struct inode *inode, const char *name, int flags) | ||
244 | { | ||
245 | struct dentry *xafile; | ||
246 | struct file *fp; | ||
247 | |||
248 | xafile = get_xa_file_dentry (inode, name, flags); | ||
249 | if (IS_ERR (xafile)) | ||
250 | return ERR_PTR (PTR_ERR (xafile)); | ||
251 | else if (!xafile->d_inode) { | ||
252 | dput (xafile); | ||
253 | return ERR_PTR (-ENODATA); | ||
254 | } | ||
255 | |||
256 | fp = dentry_open (xafile, NULL, O_RDWR); | ||
257 | /* dentry_open dputs the dentry if it fails */ | ||
258 | |||
259 | return fp; | ||
260 | } | ||
261 | |||
262 | |||
263 | /* | ||
264 | * this is very similar to fs/reiserfs/dir.c:reiserfs_readdir, but | ||
265 | * we need to drop the path before calling the filldir struct. That | ||
266 | * would be a big performance hit to the non-xattr case, so I've copied | ||
267 | * the whole thing for now. --clm | ||
268 | * | ||
269 | * the big difference is that I go backwards through the directory, | ||
270 | * and don't mess with f->f_pos, but the idea is the same. Do some | ||
271 | * action on each and every entry in the directory. | ||
272 | * | ||
273 | * we're called with i_sem held, so there are no worries about the directory | ||
274 | * changing underneath us. | ||
275 | */ | ||
276 | static int __xattr_readdir(struct file * filp, void * dirent, filldir_t filldir) | ||
277 | { | ||
278 | struct inode *inode = filp->f_dentry->d_inode; | ||
279 | struct cpu_key pos_key; /* key of current position in the directory (key of directory entry) */ | ||
280 | INITIALIZE_PATH (path_to_entry); | ||
281 | struct buffer_head * bh; | ||
282 | int entry_num; | ||
283 | struct item_head * ih, tmp_ih; | ||
284 | int search_res; | ||
285 | char * local_buf; | ||
286 | loff_t next_pos; | ||
287 | char small_buf[32] ; /* avoid kmalloc if we can */ | ||
288 | struct reiserfs_de_head *deh; | ||
289 | int d_reclen; | ||
290 | char * d_name; | ||
291 | off_t d_off; | ||
292 | ino_t d_ino; | ||
293 | struct reiserfs_dir_entry de; | ||
294 | |||
295 | |||
296 | /* form key for search the next directory entry using f_pos field of | ||
297 | file structure */ | ||
298 | next_pos = max_reiserfs_offset(inode); | ||
299 | |||
300 | while (1) { | ||
301 | research: | ||
302 | if (next_pos <= DOT_DOT_OFFSET) | ||
303 | break; | ||
304 | make_cpu_key (&pos_key, inode, next_pos, TYPE_DIRENTRY, 3); | ||
305 | |||
306 | search_res = search_by_entry_key(inode->i_sb, &pos_key, &path_to_entry, &de); | ||
307 | if (search_res == IO_ERROR) { | ||
308 | // FIXME: we could just skip part of directory which could | ||
309 | // not be read | ||
310 | pathrelse(&path_to_entry); | ||
311 | return -EIO; | ||
312 | } | ||
313 | |||
314 | if (search_res == NAME_NOT_FOUND) | ||
315 | de.de_entry_num--; | ||
316 | |||
317 | set_de_name_and_namelen(&de); | ||
318 | entry_num = de.de_entry_num; | ||
319 | deh = &(de.de_deh[entry_num]); | ||
320 | |||
321 | bh = de.de_bh; | ||
322 | ih = de.de_ih; | ||
323 | |||
324 | if (!is_direntry_le_ih(ih)) { | ||
325 | reiserfs_warning(inode->i_sb, "not direntry %h", ih); | ||
326 | break; | ||
327 | } | ||
328 | copy_item_head(&tmp_ih, ih); | ||
329 | |||
330 | /* we must have found item, that is item of this directory, */ | ||
331 | RFALSE( COMP_SHORT_KEYS (&(ih->ih_key), &pos_key), | ||
332 | "vs-9000: found item %h does not match to dir we readdir %K", | ||
333 | ih, &pos_key); | ||
334 | |||
335 | if (deh_offset(deh) <= DOT_DOT_OFFSET) { | ||
336 | break; | ||
337 | } | ||
338 | |||
339 | /* look for the previous entry in the directory */ | ||
340 | next_pos = deh_offset (deh) - 1; | ||
341 | |||
342 | if (!de_visible (deh)) | ||
343 | /* it is hidden entry */ | ||
344 | continue; | ||
345 | |||
346 | d_reclen = entry_length(bh, ih, entry_num); | ||
347 | d_name = B_I_DEH_ENTRY_FILE_NAME (bh, ih, deh); | ||
348 | d_off = deh_offset (deh); | ||
349 | d_ino = deh_objectid (deh); | ||
350 | |||
351 | if (!d_name[d_reclen - 1]) | ||
352 | d_reclen = strlen (d_name); | ||
353 | |||
354 | if (d_reclen > REISERFS_MAX_NAME(inode->i_sb->s_blocksize)){ | ||
355 | /* too big to send back to VFS */ | ||
356 | continue ; | ||
357 | } | ||
358 | |||
359 | /* Ignore the .reiserfs_priv entry */ | ||
360 | if (reiserfs_xattrs (inode->i_sb) && | ||
361 | !old_format_only(inode->i_sb) && | ||
362 | deh_objectid (deh) == le32_to_cpu (INODE_PKEY(REISERFS_SB(inode->i_sb)->priv_root->d_inode)->k_objectid)) | ||
363 | continue; | ||
364 | |||
365 | if (d_reclen <= 32) { | ||
366 | local_buf = small_buf ; | ||
367 | } else { | ||
368 | local_buf = reiserfs_kmalloc(d_reclen, GFP_NOFS, inode->i_sb) ; | ||
369 | if (!local_buf) { | ||
370 | pathrelse (&path_to_entry); | ||
371 | return -ENOMEM ; | ||
372 | } | ||
373 | if (item_moved (&tmp_ih, &path_to_entry)) { | ||
374 | reiserfs_kfree(local_buf, d_reclen, inode->i_sb) ; | ||
375 | |||
376 | /* sigh, must retry. Do this same offset again */ | ||
377 | next_pos = d_off; | ||
378 | goto research; | ||
379 | } | ||
380 | } | ||
381 | |||
382 | // Note, that we copy name to user space via temporary | ||
383 | // buffer (local_buf) because filldir will block if | ||
384 | // user space buffer is swapped out. At that time | ||
385 | // entry can move to somewhere else | ||
386 | memcpy (local_buf, d_name, d_reclen); | ||
387 | |||
388 | /* the filldir function might need to start transactions, | ||
389 | * or do who knows what. Release the path now that we've | ||
390 | * copied all the important stuff out of the deh | ||
391 | */ | ||
392 | pathrelse (&path_to_entry); | ||
393 | |||
394 | if (filldir (dirent, local_buf, d_reclen, d_off, d_ino, | ||
395 | DT_UNKNOWN) < 0) { | ||
396 | if (local_buf != small_buf) { | ||
397 | reiserfs_kfree(local_buf, d_reclen, inode->i_sb) ; | ||
398 | } | ||
399 | goto end; | ||
400 | } | ||
401 | if (local_buf != small_buf) { | ||
402 | reiserfs_kfree(local_buf, d_reclen, inode->i_sb) ; | ||
403 | } | ||
404 | } /* while */ | ||
405 | |||
406 | end: | ||
407 | pathrelse (&path_to_entry); | ||
408 | return 0; | ||
409 | } | ||
410 | |||
411 | /* | ||
412 | * this could be done with dedicated readdir ops for the xattr files, | ||
413 | * but I want to get something working asap | ||
414 | * this is stolen from vfs_readdir | ||
415 | * | ||
416 | */ | ||
417 | static | ||
418 | int xattr_readdir(struct file *file, filldir_t filler, void *buf) | ||
419 | { | ||
420 | struct inode *inode = file->f_dentry->d_inode; | ||
421 | int res = -ENOTDIR; | ||
422 | if (!file->f_op || !file->f_op->readdir) | ||
423 | goto out; | ||
424 | down(&inode->i_sem); | ||
425 | // down(&inode->i_zombie); | ||
426 | res = -ENOENT; | ||
427 | if (!IS_DEADDIR(inode)) { | ||
428 | lock_kernel(); | ||
429 | res = __xattr_readdir(file, buf, filler); | ||
430 | unlock_kernel(); | ||
431 | } | ||
432 | // up(&inode->i_zombie); | ||
433 | up(&inode->i_sem); | ||
434 | out: | ||
435 | return res; | ||
436 | } | ||
437 | |||
438 | |||
439 | /* Internal operations on file data */ | ||
440 | static inline void | ||
441 | reiserfs_put_page(struct page *page) | ||
442 | { | ||
443 | kunmap(page); | ||
444 | page_cache_release(page); | ||
445 | } | ||
446 | |||
447 | static struct page * | ||
448 | reiserfs_get_page(struct inode *dir, unsigned long n) | ||
449 | { | ||
450 | struct address_space *mapping = dir->i_mapping; | ||
451 | struct page *page; | ||
452 | /* We can deadlock if we try to free dentries, | ||
453 | and an unlink/rmdir has just occured - GFP_NOFS avoids this */ | ||
454 | mapping->flags = (mapping->flags & ~__GFP_BITS_MASK) | GFP_NOFS; | ||
455 | page = read_cache_page (mapping, n, | ||
456 | (filler_t*)mapping->a_ops->readpage, NULL); | ||
457 | if (!IS_ERR(page)) { | ||
458 | wait_on_page_locked(page); | ||
459 | kmap(page); | ||
460 | if (!PageUptodate(page)) | ||
461 | goto fail; | ||
462 | |||
463 | if (PageError(page)) | ||
464 | goto fail; | ||
465 | } | ||
466 | return page; | ||
467 | |||
468 | fail: | ||
469 | reiserfs_put_page(page); | ||
470 | return ERR_PTR(-EIO); | ||
471 | } | ||
472 | |||
473 | static inline __u32 | ||
474 | xattr_hash (const char *msg, int len) | ||
475 | { | ||
476 | return csum_partial (msg, len, 0); | ||
477 | } | ||
478 | |||
479 | /* Generic extended attribute operations that can be used by xa plugins */ | ||
480 | |||
481 | /* | ||
482 | * inode->i_sem: down | ||
483 | */ | ||
484 | int | ||
485 | reiserfs_xattr_set (struct inode *inode, const char *name, const void *buffer, | ||
486 | size_t buffer_size, int flags) | ||
487 | { | ||
488 | int err = 0; | ||
489 | struct file *fp; | ||
490 | struct page *page; | ||
491 | char *data; | ||
492 | struct address_space *mapping; | ||
493 | size_t file_pos = 0; | ||
494 | size_t buffer_pos = 0; | ||
495 | struct inode *xinode; | ||
496 | struct iattr newattrs; | ||
497 | __u32 xahash = 0; | ||
498 | |||
499 | if (IS_RDONLY (inode)) | ||
500 | return -EROFS; | ||
501 | |||
502 | if (IS_IMMUTABLE (inode) || IS_APPEND (inode)) | ||
503 | return -EPERM; | ||
504 | |||
505 | if (get_inode_sd_version (inode) == STAT_DATA_V1) | ||
506 | return -EOPNOTSUPP; | ||
507 | |||
508 | /* Empty xattrs are ok, they're just empty files, no hash */ | ||
509 | if (buffer && buffer_size) | ||
510 | xahash = xattr_hash (buffer, buffer_size); | ||
511 | |||
512 | open_file: | ||
513 | fp = open_xa_file (inode, name, flags); | ||
514 | if (IS_ERR (fp)) { | ||
515 | err = PTR_ERR (fp); | ||
516 | goto out; | ||
517 | } | ||
518 | |||
519 | xinode = fp->f_dentry->d_inode; | ||
520 | REISERFS_I(inode)->i_flags |= i_has_xattr_dir; | ||
521 | |||
522 | /* we need to copy it off.. */ | ||
523 | if (xinode->i_nlink > 1) { | ||
524 | fput(fp); | ||
525 | err = reiserfs_xattr_del (inode, name); | ||
526 | if (err < 0) | ||
527 | goto out; | ||
528 | /* We just killed the old one, we're not replacing anymore */ | ||
529 | if (flags & XATTR_REPLACE) | ||
530 | flags &= ~XATTR_REPLACE; | ||
531 | goto open_file; | ||
532 | } | ||
533 | |||
534 | /* Resize it so we're ok to write there */ | ||
535 | newattrs.ia_size = buffer_size; | ||
536 | newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME; | ||
537 | down (&xinode->i_sem); | ||
538 | err = notify_change(fp->f_dentry, &newattrs); | ||
539 | if (err) | ||
540 | goto out_filp; | ||
541 | |||
542 | mapping = xinode->i_mapping; | ||
543 | while (buffer_pos < buffer_size || buffer_pos == 0) { | ||
544 | size_t chunk; | ||
545 | size_t skip = 0; | ||
546 | size_t page_offset = (file_pos & (PAGE_CACHE_SIZE - 1)); | ||
547 | if (buffer_size - buffer_pos > PAGE_CACHE_SIZE) | ||
548 | chunk = PAGE_CACHE_SIZE; | ||
549 | else | ||
550 | chunk = buffer_size - buffer_pos; | ||
551 | |||
552 | page = reiserfs_get_page (xinode, file_pos >> PAGE_CACHE_SHIFT); | ||
553 | if (IS_ERR (page)) { | ||
554 | err = PTR_ERR (page); | ||
555 | goto out_filp; | ||
556 | } | ||
557 | |||
558 | lock_page (page); | ||
559 | data = page_address (page); | ||
560 | |||
561 | if (file_pos == 0) { | ||
562 | struct reiserfs_xattr_header *rxh; | ||
563 | skip = file_pos = sizeof (struct reiserfs_xattr_header); | ||
564 | if (chunk + skip > PAGE_CACHE_SIZE) | ||
565 | chunk = PAGE_CACHE_SIZE - skip; | ||
566 | rxh = (struct reiserfs_xattr_header *)data; | ||
567 | rxh->h_magic = cpu_to_le32 (REISERFS_XATTR_MAGIC); | ||
568 | rxh->h_hash = cpu_to_le32 (xahash); | ||
569 | } | ||
570 | |||
571 | err = mapping->a_ops->prepare_write (fp, page, page_offset, | ||
572 | page_offset + chunk + skip); | ||
573 | if (!err) { | ||
574 | if (buffer) | ||
575 | memcpy (data + skip, buffer + buffer_pos, chunk); | ||
576 | err = mapping->a_ops->commit_write (fp, page, page_offset, | ||
577 | page_offset + chunk + skip); | ||
578 | } | ||
579 | unlock_page (page); | ||
580 | reiserfs_put_page (page); | ||
581 | buffer_pos += chunk; | ||
582 | file_pos += chunk; | ||
583 | skip = 0; | ||
584 | if (err || buffer_size == 0 || !buffer) | ||
585 | break; | ||
586 | } | ||
587 | |||
588 | /* We can't mark the inode dirty if it's not hashed. This is the case | ||
589 | * when we're inheriting the default ACL. If we dirty it, the inode | ||
590 | * gets marked dirty, but won't (ever) make it onto the dirty list until | ||
591 | * it's synced explicitly to clear I_DIRTY. This is bad. */ | ||
592 | if (!hlist_unhashed(&inode->i_hash)) { | ||
593 | inode->i_ctime = CURRENT_TIME_SEC; | ||
594 | mark_inode_dirty (inode); | ||
595 | } | ||
596 | |||
597 | out_filp: | ||
598 | up (&xinode->i_sem); | ||
599 | fput(fp); | ||
600 | |||
601 | out: | ||
602 | return err; | ||
603 | } | ||
604 | |||
605 | /* | ||
606 | * inode->i_sem: down | ||
607 | */ | ||
608 | int | ||
609 | reiserfs_xattr_get (const struct inode *inode, const char *name, void *buffer, | ||
610 | size_t buffer_size) | ||
611 | { | ||
612 | ssize_t err = 0; | ||
613 | struct file *fp; | ||
614 | size_t isize; | ||
615 | size_t file_pos = 0; | ||
616 | size_t buffer_pos = 0; | ||
617 | struct page *page; | ||
618 | struct inode *xinode; | ||
619 | __u32 hash = 0; | ||
620 | |||
621 | if (name == NULL) | ||
622 | return -EINVAL; | ||
623 | |||
624 | /* We can't have xattrs attached to v1 items since they don't have | ||
625 | * generation numbers */ | ||
626 | if (get_inode_sd_version (inode) == STAT_DATA_V1) | ||
627 | return -EOPNOTSUPP; | ||
628 | |||
629 | fp = open_xa_file (inode, name, FL_READONLY); | ||
630 | if (IS_ERR (fp)) { | ||
631 | err = PTR_ERR (fp); | ||
632 | goto out; | ||
633 | } | ||
634 | |||
635 | xinode = fp->f_dentry->d_inode; | ||
636 | isize = xinode->i_size; | ||
637 | REISERFS_I(inode)->i_flags |= i_has_xattr_dir; | ||
638 | |||
639 | /* Just return the size needed */ | ||
640 | if (buffer == NULL) { | ||
641 | err = isize - sizeof (struct reiserfs_xattr_header); | ||
642 | goto out_dput; | ||
643 | } | ||
644 | |||
645 | if (buffer_size < isize - sizeof (struct reiserfs_xattr_header)) { | ||
646 | err = -ERANGE; | ||
647 | goto out_dput; | ||
648 | } | ||
649 | |||
650 | while (file_pos < isize) { | ||
651 | size_t chunk; | ||
652 | char *data; | ||
653 | size_t skip = 0; | ||
654 | if (isize - file_pos > PAGE_CACHE_SIZE) | ||
655 | chunk = PAGE_CACHE_SIZE; | ||
656 | else | ||
657 | chunk = isize - file_pos; | ||
658 | |||
659 | page = reiserfs_get_page (xinode, file_pos >> PAGE_CACHE_SHIFT); | ||
660 | if (IS_ERR (page)) { | ||
661 | err = PTR_ERR (page); | ||
662 | goto out_dput; | ||
663 | } | ||
664 | |||
665 | lock_page (page); | ||
666 | data = page_address (page); | ||
667 | if (file_pos == 0) { | ||
668 | struct reiserfs_xattr_header *rxh = | ||
669 | (struct reiserfs_xattr_header *)data; | ||
670 | skip = file_pos = sizeof (struct reiserfs_xattr_header); | ||
671 | chunk -= skip; | ||
672 | /* Magic doesn't match up.. */ | ||
673 | if (rxh->h_magic != cpu_to_le32 (REISERFS_XATTR_MAGIC)) { | ||
674 | unlock_page (page); | ||
675 | reiserfs_put_page (page); | ||
676 | reiserfs_warning (inode->i_sb, "Invalid magic for xattr (%s) " | ||
677 | "associated with %k", name, | ||
678 | INODE_PKEY (inode)); | ||
679 | err = -EIO; | ||
680 | goto out_dput; | ||
681 | } | ||
682 | hash = le32_to_cpu (rxh->h_hash); | ||
683 | } | ||
684 | memcpy (buffer + buffer_pos, data + skip, chunk); | ||
685 | unlock_page (page); | ||
686 | reiserfs_put_page (page); | ||
687 | file_pos += chunk; | ||
688 | buffer_pos += chunk; | ||
689 | skip = 0; | ||
690 | } | ||
691 | err = isize - sizeof (struct reiserfs_xattr_header); | ||
692 | |||
693 | if (xattr_hash (buffer, isize - sizeof (struct reiserfs_xattr_header)) != hash) { | ||
694 | reiserfs_warning (inode->i_sb, "Invalid hash for xattr (%s) associated " | ||
695 | "with %k", name, INODE_PKEY (inode)); | ||
696 | err = -EIO; | ||
697 | } | ||
698 | |||
699 | out_dput: | ||
700 | fput(fp); | ||
701 | |||
702 | out: | ||
703 | return err; | ||
704 | } | ||
705 | |||
706 | static int | ||
707 | __reiserfs_xattr_del (struct dentry *xadir, const char *name, int namelen) | ||
708 | { | ||
709 | struct dentry *dentry; | ||
710 | struct inode *dir = xadir->d_inode; | ||
711 | int err = 0; | ||
712 | |||
713 | dentry = lookup_one_len (name, xadir, namelen); | ||
714 | if (IS_ERR (dentry)) { | ||
715 | err = PTR_ERR (dentry); | ||
716 | goto out; | ||
717 | } else if (!dentry->d_inode) { | ||
718 | err = -ENODATA; | ||
719 | goto out_file; | ||
720 | } | ||
721 | |||
722 | /* Skip directories.. */ | ||
723 | if (S_ISDIR (dentry->d_inode->i_mode)) | ||
724 | goto out_file; | ||
725 | |||
726 | if (!is_reiserfs_priv_object (dentry->d_inode)) { | ||
727 | reiserfs_warning (dir->i_sb, "OID %08x [%.*s/%.*s] doesn't have " | ||
728 | "priv flag set [parent is %sset].", | ||
729 | le32_to_cpu (INODE_PKEY (dentry->d_inode)->k_objectid), | ||
730 | xadir->d_name.len, xadir->d_name.name, namelen, name, | ||
731 | is_reiserfs_priv_object (xadir->d_inode) ? "" : "not "); | ||
732 | dput (dentry); | ||
733 | return -EIO; | ||
734 | } | ||
735 | |||
736 | err = dir->i_op->unlink (dir, dentry); | ||
737 | if (!err) | ||
738 | d_delete (dentry); | ||
739 | |||
740 | out_file: | ||
741 | dput (dentry); | ||
742 | |||
743 | out: | ||
744 | return err; | ||
745 | } | ||
746 | |||
747 | |||
748 | int | ||
749 | reiserfs_xattr_del (struct inode *inode, const char *name) | ||
750 | { | ||
751 | struct dentry *dir; | ||
752 | int err; | ||
753 | |||
754 | if (IS_RDONLY (inode)) | ||
755 | return -EROFS; | ||
756 | |||
757 | dir = open_xa_dir (inode, FL_READONLY); | ||
758 | if (IS_ERR (dir)) { | ||
759 | err = PTR_ERR (dir); | ||
760 | goto out; | ||
761 | } | ||
762 | |||
763 | err = __reiserfs_xattr_del (dir, name, strlen (name)); | ||
764 | dput (dir); | ||
765 | |||
766 | if (!err) { | ||
767 | inode->i_ctime = CURRENT_TIME_SEC; | ||
768 | mark_inode_dirty (inode); | ||
769 | } | ||
770 | |||
771 | out: | ||
772 | return err; | ||
773 | } | ||
774 | |||
775 | /* The following are side effects of other operations that aren't explicitly | ||
776 | * modifying extended attributes. This includes operations such as permissions | ||
777 | * or ownership changes, object deletions, etc. */ | ||
778 | |||
779 | static int | ||
780 | reiserfs_delete_xattrs_filler (void *buf, const char *name, int namelen, | ||
781 | loff_t offset, ino_t ino, unsigned int d_type) | ||
782 | { | ||
783 | struct dentry *xadir = (struct dentry *)buf; | ||
784 | |||
785 | return __reiserfs_xattr_del (xadir, name, namelen); | ||
786 | |||
787 | } | ||
788 | |||
789 | /* This is called w/ inode->i_sem downed */ | ||
790 | int | ||
791 | reiserfs_delete_xattrs (struct inode *inode) | ||
792 | { | ||
793 | struct file *fp; | ||
794 | struct dentry *dir, *root; | ||
795 | int err = 0; | ||
796 | |||
797 | /* Skip out, an xattr has no xattrs associated with it */ | ||
798 | if (is_reiserfs_priv_object (inode) || | ||
799 | get_inode_sd_version (inode) == STAT_DATA_V1 || | ||
800 | !reiserfs_xattrs(inode->i_sb)) | ||
801 | { | ||
802 | return 0; | ||
803 | } | ||
804 | reiserfs_read_lock_xattrs (inode->i_sb); | ||
805 | dir = open_xa_dir (inode, FL_READONLY); | ||
806 | reiserfs_read_unlock_xattrs (inode->i_sb); | ||
807 | if (IS_ERR (dir)) { | ||
808 | err = PTR_ERR (dir); | ||
809 | goto out; | ||
810 | } else if (!dir->d_inode) { | ||
811 | dput (dir); | ||
812 | return 0; | ||
813 | } | ||
814 | |||
815 | fp = dentry_open (dir, NULL, O_RDWR); | ||
816 | if (IS_ERR (fp)) { | ||
817 | err = PTR_ERR (fp); | ||
818 | /* dentry_open dputs the dentry if it fails */ | ||
819 | goto out; | ||
820 | } | ||
821 | |||
822 | lock_kernel (); | ||
823 | err = xattr_readdir (fp, reiserfs_delete_xattrs_filler, dir); | ||
824 | if (err) { | ||
825 | unlock_kernel (); | ||
826 | goto out_dir; | ||
827 | } | ||
828 | |||
829 | /* Leftovers besides . and .. -- that's not good. */ | ||
830 | if (dir->d_inode->i_nlink <= 2) { | ||
831 | root = get_xa_root (inode->i_sb); | ||
832 | reiserfs_write_lock_xattrs (inode->i_sb); | ||
833 | err = vfs_rmdir (root->d_inode, dir); | ||
834 | reiserfs_write_unlock_xattrs (inode->i_sb); | ||
835 | dput (root); | ||
836 | } else { | ||
837 | reiserfs_warning (inode->i_sb, | ||
838 | "Couldn't remove all entries in directory"); | ||
839 | } | ||
840 | unlock_kernel (); | ||
841 | |||
842 | out_dir: | ||
843 | fput(fp); | ||
844 | |||
845 | out: | ||
846 | if (!err) | ||
847 | REISERFS_I(inode)->i_flags = REISERFS_I(inode)->i_flags & ~i_has_xattr_dir; | ||
848 | return err; | ||
849 | } | ||
850 | |||
851 | struct reiserfs_chown_buf { | ||
852 | struct inode *inode; | ||
853 | struct dentry *xadir; | ||
854 | struct iattr *attrs; | ||
855 | }; | ||
856 | |||
857 | /* XXX: If there is a better way to do this, I'd love to hear about it */ | ||
858 | static int | ||
859 | reiserfs_chown_xattrs_filler (void *buf, const char *name, int namelen, | ||
860 | loff_t offset, ino_t ino, unsigned int d_type) | ||
861 | { | ||
862 | struct reiserfs_chown_buf *chown_buf = (struct reiserfs_chown_buf *)buf; | ||
863 | struct dentry *xafile, *xadir = chown_buf->xadir; | ||
864 | struct iattr *attrs = chown_buf->attrs; | ||
865 | int err = 0; | ||
866 | |||
867 | xafile = lookup_one_len (name, xadir, namelen); | ||
868 | if (IS_ERR (xafile)) | ||
869 | return PTR_ERR (xafile); | ||
870 | else if (!xafile->d_inode) { | ||
871 | dput (xafile); | ||
872 | return -ENODATA; | ||
873 | } | ||
874 | |||
875 | if (!S_ISDIR (xafile->d_inode->i_mode)) | ||
876 | err = notify_change (xafile, attrs); | ||
877 | dput (xafile); | ||
878 | |||
879 | return err; | ||
880 | } | ||
881 | |||
882 | int | ||
883 | reiserfs_chown_xattrs (struct inode *inode, struct iattr *attrs) | ||
884 | { | ||
885 | struct file *fp; | ||
886 | struct dentry *dir; | ||
887 | int err = 0; | ||
888 | struct reiserfs_chown_buf buf; | ||
889 | unsigned int ia_valid = attrs->ia_valid; | ||
890 | |||
891 | /* Skip out, an xattr has no xattrs associated with it */ | ||
892 | if (is_reiserfs_priv_object (inode) || | ||
893 | get_inode_sd_version (inode) == STAT_DATA_V1 || | ||
894 | !reiserfs_xattrs(inode->i_sb)) | ||
895 | { | ||
896 | return 0; | ||
897 | } | ||
898 | reiserfs_read_lock_xattrs (inode->i_sb); | ||
899 | dir = open_xa_dir (inode, FL_READONLY); | ||
900 | reiserfs_read_unlock_xattrs (inode->i_sb); | ||
901 | if (IS_ERR (dir)) { | ||
902 | if (PTR_ERR (dir) != -ENODATA) | ||
903 | err = PTR_ERR (dir); | ||
904 | goto out; | ||
905 | } else if (!dir->d_inode) { | ||
906 | dput (dir); | ||
907 | goto out; | ||
908 | } | ||
909 | |||
910 | fp = dentry_open (dir, NULL, O_RDWR); | ||
911 | if (IS_ERR (fp)) { | ||
912 | err = PTR_ERR (fp); | ||
913 | /* dentry_open dputs the dentry if it fails */ | ||
914 | goto out; | ||
915 | } | ||
916 | |||
917 | lock_kernel (); | ||
918 | |||
919 | attrs->ia_valid &= (ATTR_UID | ATTR_GID | ATTR_CTIME); | ||
920 | buf.xadir = dir; | ||
921 | buf.attrs = attrs; | ||
922 | buf.inode = inode; | ||
923 | |||
924 | err = xattr_readdir (fp, reiserfs_chown_xattrs_filler, &buf); | ||
925 | if (err) { | ||
926 | unlock_kernel (); | ||
927 | goto out_dir; | ||
928 | } | ||
929 | |||
930 | err = notify_change (dir, attrs); | ||
931 | unlock_kernel (); | ||
932 | |||
933 | out_dir: | ||
934 | fput(fp); | ||
935 | |||
936 | out: | ||
937 | attrs->ia_valid = ia_valid; | ||
938 | return err; | ||
939 | } | ||
940 | |||
941 | |||
942 | /* Actual operations that are exported to VFS-land */ | ||
943 | |||
944 | /* | ||
945 | * Inode operation getxattr() | ||
946 | * Preliminary locking: we down dentry->d_inode->i_sem | ||
947 | */ | ||
948 | ssize_t | ||
949 | reiserfs_getxattr (struct dentry *dentry, const char *name, void *buffer, | ||
950 | size_t size) | ||
951 | { | ||
952 | struct reiserfs_xattr_handler *xah = find_xattr_handler_prefix (name); | ||
953 | int err; | ||
954 | |||
955 | if (!xah || !reiserfs_xattrs(dentry->d_sb) || | ||
956 | get_inode_sd_version (dentry->d_inode) == STAT_DATA_V1) | ||
957 | return -EOPNOTSUPP; | ||
958 | |||
959 | reiserfs_read_lock_xattr_i (dentry->d_inode); | ||
960 | reiserfs_read_lock_xattrs (dentry->d_sb); | ||
961 | err = xah->get (dentry->d_inode, name, buffer, size); | ||
962 | reiserfs_read_unlock_xattrs (dentry->d_sb); | ||
963 | reiserfs_read_unlock_xattr_i (dentry->d_inode); | ||
964 | return err; | ||
965 | } | ||
966 | |||
967 | |||
968 | /* | ||
969 | * Inode operation setxattr() | ||
970 | * | ||
971 | * dentry->d_inode->i_sem down | ||
972 | */ | ||
973 | int | ||
974 | reiserfs_setxattr (struct dentry *dentry, const char *name, const void *value, | ||
975 | size_t size, int flags) | ||
976 | { | ||
977 | struct reiserfs_xattr_handler *xah = find_xattr_handler_prefix (name); | ||
978 | int err; | ||
979 | int lock; | ||
980 | |||
981 | if (!xah || !reiserfs_xattrs(dentry->d_sb) || | ||
982 | get_inode_sd_version (dentry->d_inode) == STAT_DATA_V1) | ||
983 | return -EOPNOTSUPP; | ||
984 | |||
985 | if (IS_RDONLY (dentry->d_inode)) | ||
986 | return -EROFS; | ||
987 | |||
988 | if (IS_IMMUTABLE (dentry->d_inode) || IS_APPEND (dentry->d_inode)) | ||
989 | return -EROFS; | ||
990 | |||
991 | reiserfs_write_lock_xattr_i (dentry->d_inode); | ||
992 | lock = !has_xattr_dir (dentry->d_inode); | ||
993 | if (lock) | ||
994 | reiserfs_write_lock_xattrs (dentry->d_sb); | ||
995 | else | ||
996 | reiserfs_read_lock_xattrs (dentry->d_sb); | ||
997 | err = xah->set (dentry->d_inode, name, value, size, flags); | ||
998 | if (lock) | ||
999 | reiserfs_write_unlock_xattrs (dentry->d_sb); | ||
1000 | else | ||
1001 | reiserfs_read_unlock_xattrs (dentry->d_sb); | ||
1002 | reiserfs_write_unlock_xattr_i (dentry->d_inode); | ||
1003 | return err; | ||
1004 | } | ||
1005 | |||
1006 | /* | ||
1007 | * Inode operation removexattr() | ||
1008 | * | ||
1009 | * dentry->d_inode->i_sem down | ||
1010 | */ | ||
1011 | int | ||
1012 | reiserfs_removexattr (struct dentry *dentry, const char *name) | ||
1013 | { | ||
1014 | int err; | ||
1015 | struct reiserfs_xattr_handler *xah = find_xattr_handler_prefix (name); | ||
1016 | |||
1017 | if (!xah || !reiserfs_xattrs(dentry->d_sb) || | ||
1018 | get_inode_sd_version (dentry->d_inode) == STAT_DATA_V1) | ||
1019 | return -EOPNOTSUPP; | ||
1020 | |||
1021 | if (IS_RDONLY (dentry->d_inode)) | ||
1022 | return -EROFS; | ||
1023 | |||
1024 | if (IS_IMMUTABLE (dentry->d_inode) || IS_APPEND (dentry->d_inode)) | ||
1025 | return -EPERM; | ||
1026 | |||
1027 | reiserfs_write_lock_xattr_i (dentry->d_inode); | ||
1028 | reiserfs_read_lock_xattrs (dentry->d_sb); | ||
1029 | |||
1030 | /* Deletion pre-operation */ | ||
1031 | if (xah->del) { | ||
1032 | err = xah->del (dentry->d_inode, name); | ||
1033 | if (err) | ||
1034 | goto out; | ||
1035 | } | ||
1036 | |||
1037 | err = reiserfs_xattr_del (dentry->d_inode, name); | ||
1038 | |||
1039 | dentry->d_inode->i_ctime = CURRENT_TIME_SEC; | ||
1040 | mark_inode_dirty (dentry->d_inode); | ||
1041 | |||
1042 | out: | ||
1043 | reiserfs_read_unlock_xattrs (dentry->d_sb); | ||
1044 | reiserfs_write_unlock_xattr_i (dentry->d_inode); | ||
1045 | return err; | ||
1046 | } | ||
1047 | |||
1048 | |||
1049 | /* This is what filldir will use: | ||
1050 | * r_pos will always contain the amount of space required for the entire | ||
1051 | * list. If r_pos becomes larger than r_size, we need more space and we | ||
1052 | * return an error indicating this. If r_pos is less than r_size, then we've | ||
1053 | * filled the buffer successfully and we return success */ | ||
1054 | struct reiserfs_listxattr_buf { | ||
1055 | int r_pos; | ||
1056 | int r_size; | ||
1057 | char *r_buf; | ||
1058 | struct inode *r_inode; | ||
1059 | }; | ||
1060 | |||
1061 | static int | ||
1062 | reiserfs_listxattr_filler (void *buf, const char *name, int namelen, | ||
1063 | loff_t offset, ino_t ino, unsigned int d_type) | ||
1064 | { | ||
1065 | struct reiserfs_listxattr_buf *b = (struct reiserfs_listxattr_buf *)buf; | ||
1066 | int len = 0; | ||
1067 | if (name[0] != '.' || (namelen != 1 && (name[1] != '.' || namelen != 2))) { | ||
1068 | struct reiserfs_xattr_handler *xah = find_xattr_handler_prefix (name); | ||
1069 | if (!xah) return 0; /* Unsupported xattr name, skip it */ | ||
1070 | |||
1071 | /* We call ->list() twice because the operation isn't required to just | ||
1072 | * return the name back - we want to make sure we have enough space */ | ||
1073 | len += xah->list (b->r_inode, name, namelen, NULL); | ||
1074 | |||
1075 | if (len) { | ||
1076 | if (b->r_pos + len + 1 <= b->r_size) { | ||
1077 | char *p = b->r_buf + b->r_pos; | ||
1078 | p += xah->list (b->r_inode, name, namelen, p); | ||
1079 | *p++ = '\0'; | ||
1080 | } | ||
1081 | b->r_pos += len + 1; | ||
1082 | } | ||
1083 | } | ||
1084 | |||
1085 | return 0; | ||
1086 | } | ||
1087 | /* | ||
1088 | * Inode operation listxattr() | ||
1089 | * | ||
1090 | * Preliminary locking: we down dentry->d_inode->i_sem | ||
1091 | */ | ||
1092 | ssize_t | ||
1093 | reiserfs_listxattr (struct dentry *dentry, char *buffer, size_t size) | ||
1094 | { | ||
1095 | struct file *fp; | ||
1096 | struct dentry *dir; | ||
1097 | int err = 0; | ||
1098 | struct reiserfs_listxattr_buf buf; | ||
1099 | |||
1100 | if (!dentry->d_inode) | ||
1101 | return -EINVAL; | ||
1102 | |||
1103 | if (!reiserfs_xattrs(dentry->d_sb) || | ||
1104 | get_inode_sd_version (dentry->d_inode) == STAT_DATA_V1) | ||
1105 | return -EOPNOTSUPP; | ||
1106 | |||
1107 | reiserfs_read_lock_xattr_i (dentry->d_inode); | ||
1108 | reiserfs_read_lock_xattrs (dentry->d_sb); | ||
1109 | dir = open_xa_dir (dentry->d_inode, FL_READONLY); | ||
1110 | reiserfs_read_unlock_xattrs (dentry->d_sb); | ||
1111 | if (IS_ERR (dir)) { | ||
1112 | err = PTR_ERR (dir); | ||
1113 | if (err == -ENODATA) | ||
1114 | err = 0; /* Not an error if there aren't any xattrs */ | ||
1115 | goto out; | ||
1116 | } | ||
1117 | |||
1118 | fp = dentry_open (dir, NULL, O_RDWR); | ||
1119 | if (IS_ERR (fp)) { | ||
1120 | err = PTR_ERR (fp); | ||
1121 | /* dentry_open dputs the dentry if it fails */ | ||
1122 | goto out; | ||
1123 | } | ||
1124 | |||
1125 | buf.r_buf = buffer; | ||
1126 | buf.r_size = buffer ? size : 0; | ||
1127 | buf.r_pos = 0; | ||
1128 | buf.r_inode = dentry->d_inode; | ||
1129 | |||
1130 | REISERFS_I(dentry->d_inode)->i_flags |= i_has_xattr_dir; | ||
1131 | |||
1132 | err = xattr_readdir (fp, reiserfs_listxattr_filler, &buf); | ||
1133 | if (err) | ||
1134 | goto out_dir; | ||
1135 | |||
1136 | if (buf.r_pos > buf.r_size && buffer != NULL) | ||
1137 | err = -ERANGE; | ||
1138 | else | ||
1139 | err = buf.r_pos; | ||
1140 | |||
1141 | out_dir: | ||
1142 | fput(fp); | ||
1143 | |||
1144 | out: | ||
1145 | reiserfs_read_unlock_xattr_i (dentry->d_inode); | ||
1146 | return err; | ||
1147 | } | ||
1148 | |||
1149 | /* This is the implementation for the xattr plugin infrastructure */ | ||
1150 | static struct list_head xattr_handlers = LIST_HEAD_INIT (xattr_handlers); | ||
1151 | static DEFINE_RWLOCK(handler_lock); | ||
1152 | |||
1153 | static struct reiserfs_xattr_handler * | ||
1154 | find_xattr_handler_prefix (const char *prefix) | ||
1155 | { | ||
1156 | struct reiserfs_xattr_handler *xah = NULL; | ||
1157 | struct list_head *p; | ||
1158 | |||
1159 | read_lock (&handler_lock); | ||
1160 | list_for_each (p, &xattr_handlers) { | ||
1161 | xah = list_entry (p, struct reiserfs_xattr_handler, handlers); | ||
1162 | if (strncmp (xah->prefix, prefix, strlen (xah->prefix)) == 0) | ||
1163 | break; | ||
1164 | xah = NULL; | ||
1165 | } | ||
1166 | |||
1167 | read_unlock (&handler_lock); | ||
1168 | return xah; | ||
1169 | } | ||
1170 | |||
1171 | static void | ||
1172 | __unregister_handlers (void) | ||
1173 | { | ||
1174 | struct reiserfs_xattr_handler *xah; | ||
1175 | struct list_head *p, *tmp; | ||
1176 | |||
1177 | list_for_each_safe (p, tmp, &xattr_handlers) { | ||
1178 | xah = list_entry (p, struct reiserfs_xattr_handler, handlers); | ||
1179 | if (xah->exit) | ||
1180 | xah->exit(); | ||
1181 | |||
1182 | list_del_init (p); | ||
1183 | } | ||
1184 | INIT_LIST_HEAD (&xattr_handlers); | ||
1185 | } | ||
1186 | |||
1187 | int __init | ||
1188 | reiserfs_xattr_register_handlers (void) | ||
1189 | { | ||
1190 | int err = 0; | ||
1191 | struct reiserfs_xattr_handler *xah; | ||
1192 | struct list_head *p; | ||
1193 | |||
1194 | write_lock (&handler_lock); | ||
1195 | |||
1196 | /* If we're already initialized, nothing to do */ | ||
1197 | if (!list_empty (&xattr_handlers)) { | ||
1198 | write_unlock (&handler_lock); | ||
1199 | return 0; | ||
1200 | } | ||
1201 | |||
1202 | /* Add the handlers */ | ||
1203 | list_add_tail (&user_handler.handlers, &xattr_handlers); | ||
1204 | list_add_tail (&trusted_handler.handlers, &xattr_handlers); | ||
1205 | #ifdef CONFIG_REISERFS_FS_SECURITY | ||
1206 | list_add_tail (&security_handler.handlers, &xattr_handlers); | ||
1207 | #endif | ||
1208 | #ifdef CONFIG_REISERFS_FS_POSIX_ACL | ||
1209 | list_add_tail (&posix_acl_access_handler.handlers, &xattr_handlers); | ||
1210 | list_add_tail (&posix_acl_default_handler.handlers, &xattr_handlers); | ||
1211 | #endif | ||
1212 | |||
1213 | /* Run initializers, if available */ | ||
1214 | list_for_each (p, &xattr_handlers) { | ||
1215 | xah = list_entry (p, struct reiserfs_xattr_handler, handlers); | ||
1216 | if (xah->init) { | ||
1217 | err = xah->init (); | ||
1218 | if (err) { | ||
1219 | list_del_init (p); | ||
1220 | break; | ||
1221 | } | ||
1222 | } | ||
1223 | } | ||
1224 | |||
1225 | /* Clean up other handlers, if any failed */ | ||
1226 | if (err) | ||
1227 | __unregister_handlers (); | ||
1228 | |||
1229 | write_unlock (&handler_lock); | ||
1230 | return err; | ||
1231 | } | ||
1232 | |||
1233 | void | ||
1234 | reiserfs_xattr_unregister_handlers (void) | ||
1235 | { | ||
1236 | write_lock (&handler_lock); | ||
1237 | __unregister_handlers (); | ||
1238 | write_unlock (&handler_lock); | ||
1239 | } | ||
1240 | |||
1241 | /* This will catch lookups from the fs root to .reiserfs_priv */ | ||
1242 | static int | ||
1243 | xattr_lookup_poison (struct dentry *dentry, struct qstr *q1, struct qstr *name) | ||
1244 | { | ||
1245 | struct dentry *priv_root = REISERFS_SB(dentry->d_sb)->priv_root; | ||
1246 | if (name->len == priv_root->d_name.len && | ||
1247 | name->hash == priv_root->d_name.hash && | ||
1248 | !memcmp (name->name, priv_root->d_name.name, name->len)) { | ||
1249 | return -ENOENT; | ||
1250 | } else if (q1->len == name->len && | ||
1251 | !memcmp(q1->name, name->name, name->len)) | ||
1252 | return 0; | ||
1253 | return 1; | ||
1254 | } | ||
1255 | |||
1256 | static struct dentry_operations xattr_lookup_poison_ops = { | ||
1257 | .d_compare = xattr_lookup_poison, | ||
1258 | }; | ||
1259 | |||
1260 | |||
1261 | /* We need to take a copy of the mount flags since things like | ||
1262 | * MS_RDONLY don't get set until *after* we're called. | ||
1263 | * mount_flags != mount_options */ | ||
1264 | int | ||
1265 | reiserfs_xattr_init (struct super_block *s, int mount_flags) | ||
1266 | { | ||
1267 | int err = 0; | ||
1268 | |||
1269 | /* We need generation numbers to ensure that the oid mapping is correct | ||
1270 | * v3.5 filesystems don't have them. */ | ||
1271 | if (!old_format_only (s)) { | ||
1272 | set_bit (REISERFS_XATTRS, &(REISERFS_SB(s)->s_mount_opt)); | ||
1273 | } else if (reiserfs_xattrs_optional (s)) { | ||
1274 | /* Old format filesystem, but optional xattrs have been enabled | ||
1275 | * at mount time. Error out. */ | ||
1276 | reiserfs_warning (s, "xattrs/ACLs not supported on pre v3.6 " | ||
1277 | "format filesystem. Failing mount."); | ||
1278 | err = -EOPNOTSUPP; | ||
1279 | goto error; | ||
1280 | } else { | ||
1281 | /* Old format filesystem, but no optional xattrs have been enabled. This | ||
1282 | * means we silently disable xattrs on the filesystem. */ | ||
1283 | clear_bit (REISERFS_XATTRS, &(REISERFS_SB(s)->s_mount_opt)); | ||
1284 | } | ||
1285 | |||
1286 | /* If we don't have the privroot located yet - go find it */ | ||
1287 | if (reiserfs_xattrs (s) && !REISERFS_SB(s)->priv_root) { | ||
1288 | struct dentry *dentry; | ||
1289 | dentry = lookup_one_len (PRIVROOT_NAME, s->s_root, | ||
1290 | strlen (PRIVROOT_NAME)); | ||
1291 | if (!IS_ERR (dentry)) { | ||
1292 | if (!(mount_flags & MS_RDONLY) && !dentry->d_inode) { | ||
1293 | struct inode *inode = dentry->d_parent->d_inode; | ||
1294 | down (&inode->i_sem); | ||
1295 | err = inode->i_op->mkdir (inode, dentry, 0700); | ||
1296 | up (&inode->i_sem); | ||
1297 | if (err) { | ||
1298 | dput (dentry); | ||
1299 | dentry = NULL; | ||
1300 | } | ||
1301 | |||
1302 | if (dentry && dentry->d_inode) | ||
1303 | reiserfs_warning (s, "Created %s on %s - reserved for " | ||
1304 | "xattr storage.", PRIVROOT_NAME, | ||
1305 | reiserfs_bdevname (inode->i_sb)); | ||
1306 | } else if (!dentry->d_inode) { | ||
1307 | dput (dentry); | ||
1308 | dentry = NULL; | ||
1309 | } | ||
1310 | } else | ||
1311 | err = PTR_ERR (dentry); | ||
1312 | |||
1313 | if (!err && dentry) { | ||
1314 | s->s_root->d_op = &xattr_lookup_poison_ops; | ||
1315 | reiserfs_mark_inode_private (dentry->d_inode); | ||
1316 | REISERFS_SB(s)->priv_root = dentry; | ||
1317 | } else if (!(mount_flags & MS_RDONLY)) { /* xattrs are unavailable */ | ||
1318 | /* If we're read-only it just means that the dir hasn't been | ||
1319 | * created. Not an error -- just no xattrs on the fs. We'll | ||
1320 | * check again if we go read-write */ | ||
1321 | reiserfs_warning (s, "xattrs/ACLs enabled and couldn't " | ||
1322 | "find/create .reiserfs_priv. Failing mount."); | ||
1323 | err = -EOPNOTSUPP; | ||
1324 | } | ||
1325 | } | ||
1326 | |||
1327 | error: | ||
1328 | /* This is only nonzero if there was an error initializing the xattr | ||
1329 | * directory or if there is a condition where we don't support them. */ | ||
1330 | if (err) { | ||
1331 | clear_bit (REISERFS_XATTRS, &(REISERFS_SB(s)->s_mount_opt)); | ||
1332 | clear_bit (REISERFS_XATTRS_USER, &(REISERFS_SB(s)->s_mount_opt)); | ||
1333 | clear_bit (REISERFS_POSIXACL, &(REISERFS_SB(s)->s_mount_opt)); | ||
1334 | } | ||
1335 | |||
1336 | /* The super_block MS_POSIXACL must mirror the (no)acl mount option. */ | ||
1337 | s->s_flags = s->s_flags & ~MS_POSIXACL; | ||
1338 | if (reiserfs_posixacl (s)) | ||
1339 | s->s_flags |= MS_POSIXACL; | ||
1340 | |||
1341 | return err; | ||
1342 | } | ||
1343 | |||
1344 | static int | ||
1345 | __reiserfs_permission (struct inode *inode, int mask, struct nameidata *nd, | ||
1346 | int need_lock) | ||
1347 | { | ||
1348 | umode_t mode = inode->i_mode; | ||
1349 | |||
1350 | if (mask & MAY_WRITE) { | ||
1351 | /* | ||
1352 | * Nobody gets write access to a read-only fs. | ||
1353 | */ | ||
1354 | if (IS_RDONLY(inode) && | ||
1355 | (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))) | ||
1356 | return -EROFS; | ||
1357 | |||
1358 | /* | ||
1359 | * Nobody gets write access to an immutable file. | ||
1360 | */ | ||
1361 | if (IS_IMMUTABLE(inode)) | ||
1362 | return -EACCES; | ||
1363 | } | ||
1364 | |||
1365 | /* We don't do permission checks on the internal objects. | ||
1366 | * Permissions are determined by the "owning" object. */ | ||
1367 | if (is_reiserfs_priv_object (inode)) | ||
1368 | return 0; | ||
1369 | |||
1370 | if (current->fsuid == inode->i_uid) { | ||
1371 | mode >>= 6; | ||
1372 | #ifdef CONFIG_REISERFS_FS_POSIX_ACL | ||
1373 | } else if (reiserfs_posixacl(inode->i_sb) && | ||
1374 | get_inode_sd_version (inode) != STAT_DATA_V1) { | ||
1375 | struct posix_acl *acl; | ||
1376 | |||
1377 | /* ACL can't contain additional permissions if | ||
1378 | the ACL_MASK entry is 0 */ | ||
1379 | if (!(mode & S_IRWXG)) | ||
1380 | goto check_groups; | ||
1381 | |||
1382 | if (need_lock) { | ||
1383 | reiserfs_read_lock_xattr_i (inode); | ||
1384 | reiserfs_read_lock_xattrs (inode->i_sb); | ||
1385 | } | ||
1386 | acl = reiserfs_get_acl (inode, ACL_TYPE_ACCESS); | ||
1387 | if (need_lock) { | ||
1388 | reiserfs_read_unlock_xattrs (inode->i_sb); | ||
1389 | reiserfs_read_unlock_xattr_i (inode); | ||
1390 | } | ||
1391 | if (IS_ERR (acl)) { | ||
1392 | if (PTR_ERR (acl) == -ENODATA) | ||
1393 | goto check_groups; | ||
1394 | return PTR_ERR (acl); | ||
1395 | } | ||
1396 | |||
1397 | if (acl) { | ||
1398 | int err = posix_acl_permission (inode, acl, mask); | ||
1399 | posix_acl_release (acl); | ||
1400 | if (err == -EACCES) { | ||
1401 | goto check_capabilities; | ||
1402 | } | ||
1403 | return err; | ||
1404 | } else { | ||
1405 | goto check_groups; | ||
1406 | } | ||
1407 | #endif | ||
1408 | } else { | ||
1409 | check_groups: | ||
1410 | if (in_group_p(inode->i_gid)) | ||
1411 | mode >>= 3; | ||
1412 | } | ||
1413 | |||
1414 | /* | ||
1415 | * If the DACs are ok we don't need any capability check. | ||
1416 | */ | ||
1417 | if (((mode & mask & (MAY_READ|MAY_WRITE|MAY_EXEC)) == mask)) | ||
1418 | return 0; | ||
1419 | |||
1420 | check_capabilities: | ||
1421 | /* | ||
1422 | * Read/write DACs are always overridable. | ||
1423 | * Executable DACs are overridable if at least one exec bit is set. | ||
1424 | */ | ||
1425 | if (!(mask & MAY_EXEC) || | ||
1426 | (inode->i_mode & S_IXUGO) || S_ISDIR(inode->i_mode)) | ||
1427 | if (capable(CAP_DAC_OVERRIDE)) | ||
1428 | return 0; | ||
1429 | |||
1430 | /* | ||
1431 | * Searching includes executable on directories, else just read. | ||
1432 | */ | ||
1433 | if (mask == MAY_READ || (S_ISDIR(inode->i_mode) && !(mask & MAY_WRITE))) | ||
1434 | if (capable(CAP_DAC_READ_SEARCH)) | ||
1435 | return 0; | ||
1436 | |||
1437 | return -EACCES; | ||
1438 | } | ||
1439 | |||
1440 | int | ||
1441 | reiserfs_permission (struct inode *inode, int mask, struct nameidata *nd) | ||
1442 | { | ||
1443 | return __reiserfs_permission (inode, mask, nd, 1); | ||
1444 | } | ||
1445 | |||
1446 | int | ||
1447 | reiserfs_permission_locked (struct inode *inode, int mask, struct nameidata *nd) | ||
1448 | { | ||
1449 | return __reiserfs_permission (inode, mask, nd, 0); | ||
1450 | } | ||