diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-03-30 15:29:21 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-03-30 15:33:01 -0400 |
commit | e1c502482853f84606928f5a2f2eb6da1993cda1 (patch) | |
tree | ca296007164906342a195bdf3a5305277e6af5da /fs/reiserfs/xattr.c | |
parent | 019abbc87025a030fd25008612afd4eff8a375f7 (diff) | |
parent | ee93961be1faddf9e9a638bc519145c20f0cfeba (diff) |
Merge branch 'reiserfs-updates' from Jeff Mahoney
* reiserfs-updates: (35 commits)
reiserfs: rename [cn]_* variables
reiserfs: rename p_._ variables
reiserfs: rename p_s_tb to tb
reiserfs: rename p_s_inode to inode
reiserfs: rename p_s_bh to bh
reiserfs: rename p_s_sb to sb
reiserfs: strip trailing whitespace
reiserfs: cleanup path functions
reiserfs: factor out buffer_info initialization
reiserfs: add atomic addition of selinux attributes during inode creation
reiserfs: use generic readdir for operations across all xattrs
reiserfs: journaled xattrs
reiserfs: use generic xattr handlers
reiserfs: remove i_has_xattr_dir
reiserfs: make per-inode xattr locking more fine grained
reiserfs: eliminate per-super xattr lock
reiserfs: simplify xattr internal file lookups/opens
reiserfs: Clean up xattrs when REISERFS_FS_XATTR is unset
reiserfs: remove IS_PRIVATE helpers
reiserfs: remove link detection code
...
Fixed up conflicts manually due to:
- quota name cleanups vs variable naming changes:
fs/reiserfs/inode.c
fs/reiserfs/namei.c
fs/reiserfs/stree.c
fs/reiserfs/xattr.c
- exported include header cleanups
include/linux/reiserfs_fs.h
Diffstat (limited to 'fs/reiserfs/xattr.c')
-rw-r--r-- | fs/reiserfs/xattr.c | 1373 |
1 files changed, 569 insertions, 804 deletions
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c index ae881ccd2f03..e52743e77000 100644 --- a/fs/reiserfs/xattr.c +++ b/fs/reiserfs/xattr.c | |||
@@ -27,6 +27,10 @@ | |||
27 | * these are special cases for filesystem ACLs, they are interpreted by the | 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 | 28 | * kernel, in addition, they are negatively and positively cached and attached |
29 | * to the inode so that unnecessary lookups are avoided. | 29 | * to the inode so that unnecessary lookups are avoided. |
30 | * | ||
31 | * Locking works like so: | ||
32 | * Directory components (xattr root, xattr dir) are protectd by their i_mutex. | ||
33 | * The xattrs themselves are protected by the xattr_sem. | ||
30 | */ | 34 | */ |
31 | 35 | ||
32 | #include <linux/reiserfs_fs.h> | 36 | #include <linux/reiserfs_fs.h> |
@@ -44,328 +48,332 @@ | |||
44 | #include <net/checksum.h> | 48 | #include <net/checksum.h> |
45 | #include <linux/smp_lock.h> | 49 | #include <linux/smp_lock.h> |
46 | #include <linux/stat.h> | 50 | #include <linux/stat.h> |
51 | #include <linux/quotaops.h> | ||
47 | 52 | ||
48 | #define FL_READONLY 128 | ||
49 | #define FL_DIR_SEM_HELD 256 | ||
50 | #define PRIVROOT_NAME ".reiserfs_priv" | 53 | #define PRIVROOT_NAME ".reiserfs_priv" |
51 | #define XAROOT_NAME "xattrs" | 54 | #define XAROOT_NAME "xattrs" |
52 | 55 | ||
53 | static struct reiserfs_xattr_handler *find_xattr_handler_prefix(const char | ||
54 | *prefix); | ||
55 | 56 | ||
56 | /* Returns the dentry referring to the root of the extended attribute | 57 | /* Helpers for inode ops. We do this so that we don't have all the VFS |
57 | * directory tree. If it has already been retrieved, it is used. If it | 58 | * overhead and also for proper i_mutex annotation. |
58 | * hasn't been created and the flags indicate creation is allowed, we | 59 | * dir->i_mutex must be held for all of them. */ |
59 | * attempt to create it. On error, we return a pointer-encoded error. | 60 | static int xattr_create(struct inode *dir, struct dentry *dentry, int mode) |
60 | */ | ||
61 | static struct dentry *get_xa_root(struct super_block *sb, int flags) | ||
62 | { | 61 | { |
63 | struct dentry *privroot = dget(REISERFS_SB(sb)->priv_root); | 62 | BUG_ON(!mutex_is_locked(&dir->i_mutex)); |
64 | struct dentry *xaroot; | 63 | vfs_dq_init(dir); |
64 | return dir->i_op->create(dir, dentry, mode, NULL); | ||
65 | } | ||
65 | 66 | ||
66 | /* This needs to be created at mount-time */ | 67 | static int xattr_mkdir(struct inode *dir, struct dentry *dentry, int mode) |
67 | if (!privroot) | 68 | { |
68 | return ERR_PTR(-ENODATA); | 69 | BUG_ON(!mutex_is_locked(&dir->i_mutex)); |
70 | vfs_dq_init(dir); | ||
71 | return dir->i_op->mkdir(dir, dentry, mode); | ||
72 | } | ||
69 | 73 | ||
70 | mutex_lock_nested(&privroot->d_inode->i_mutex, I_MUTEX_XATTR); | 74 | /* We use I_MUTEX_CHILD here to silence lockdep. It's safe because xattr |
71 | if (REISERFS_SB(sb)->xattr_root) { | 75 | * mutation ops aren't called during rename or splace, which are the |
72 | xaroot = dget(REISERFS_SB(sb)->xattr_root); | 76 | * only other users of I_MUTEX_CHILD. It violates the ordering, but that's |
73 | goto out; | 77 | * better than allocating another subclass just for this code. */ |
74 | } | 78 | static int xattr_unlink(struct inode *dir, struct dentry *dentry) |
79 | { | ||
80 | int error; | ||
81 | BUG_ON(!mutex_is_locked(&dir->i_mutex)); | ||
82 | vfs_dq_init(dir); | ||
75 | 83 | ||
76 | xaroot = lookup_one_len(XAROOT_NAME, privroot, strlen(XAROOT_NAME)); | 84 | mutex_lock_nested(&dentry->d_inode->i_mutex, I_MUTEX_CHILD); |
77 | if (IS_ERR(xaroot)) { | 85 | error = dir->i_op->unlink(dir, dentry); |
78 | goto out; | 86 | mutex_unlock(&dentry->d_inode->i_mutex); |
79 | } else if (!xaroot->d_inode) { | 87 | |
88 | if (!error) | ||
89 | d_delete(dentry); | ||
90 | return error; | ||
91 | } | ||
92 | |||
93 | static int xattr_rmdir(struct inode *dir, struct dentry *dentry) | ||
94 | { | ||
95 | int error; | ||
96 | BUG_ON(!mutex_is_locked(&dir->i_mutex)); | ||
97 | vfs_dq_init(dir); | ||
98 | |||
99 | mutex_lock_nested(&dentry->d_inode->i_mutex, I_MUTEX_CHILD); | ||
100 | dentry_unhash(dentry); | ||
101 | error = dir->i_op->rmdir(dir, dentry); | ||
102 | if (!error) | ||
103 | dentry->d_inode->i_flags |= S_DEAD; | ||
104 | mutex_unlock(&dentry->d_inode->i_mutex); | ||
105 | if (!error) | ||
106 | d_delete(dentry); | ||
107 | dput(dentry); | ||
108 | |||
109 | return error; | ||
110 | } | ||
111 | |||
112 | #define xattr_may_create(flags) (!flags || flags & XATTR_CREATE) | ||
113 | |||
114 | /* Returns and possibly creates the xattr dir. */ | ||
115 | static struct dentry *lookup_or_create_dir(struct dentry *parent, | ||
116 | const char *name, int flags) | ||
117 | { | ||
118 | struct dentry *dentry; | ||
119 | BUG_ON(!parent); | ||
120 | |||
121 | dentry = lookup_one_len(name, parent, strlen(name)); | ||
122 | if (IS_ERR(dentry)) | ||
123 | return dentry; | ||
124 | else if (!dentry->d_inode) { | ||
80 | int err = -ENODATA; | 125 | int err = -ENODATA; |
81 | if (flags == 0 || flags & XATTR_CREATE) | 126 | |
82 | err = privroot->d_inode->i_op->mkdir(privroot->d_inode, | 127 | if (xattr_may_create(flags)) { |
83 | xaroot, 0700); | 128 | mutex_lock_nested(&parent->d_inode->i_mutex, |
129 | I_MUTEX_XATTR); | ||
130 | err = xattr_mkdir(parent->d_inode, dentry, 0700); | ||
131 | mutex_unlock(&parent->d_inode->i_mutex); | ||
132 | } | ||
133 | |||
84 | if (err) { | 134 | if (err) { |
85 | dput(xaroot); | 135 | dput(dentry); |
86 | xaroot = ERR_PTR(err); | 136 | dentry = ERR_PTR(err); |
87 | goto out; | ||
88 | } | 137 | } |
89 | } | 138 | } |
90 | REISERFS_SB(sb)->xattr_root = dget(xaroot); | ||
91 | 139 | ||
92 | out: | 140 | return dentry; |
93 | mutex_unlock(&privroot->d_inode->i_mutex); | 141 | } |
94 | dput(privroot); | 142 | |
95 | return xaroot; | 143 | static struct dentry *open_xa_root(struct super_block *sb, int flags) |
144 | { | ||
145 | struct dentry *privroot = REISERFS_SB(sb)->priv_root; | ||
146 | if (!privroot) | ||
147 | return ERR_PTR(-ENODATA); | ||
148 | return lookup_or_create_dir(privroot, XAROOT_NAME, flags); | ||
96 | } | 149 | } |
97 | 150 | ||
98 | /* Opens the directory corresponding to the inode's extended attribute store. | ||
99 | * If flags allow, the tree to the directory may be created. If creation is | ||
100 | * prohibited, -ENODATA is returned. */ | ||
101 | static struct dentry *open_xa_dir(const struct inode *inode, int flags) | 151 | static struct dentry *open_xa_dir(const struct inode *inode, int flags) |
102 | { | 152 | { |
103 | struct dentry *xaroot, *xadir; | 153 | struct dentry *xaroot, *xadir; |
104 | char namebuf[17]; | 154 | char namebuf[17]; |
105 | 155 | ||
106 | xaroot = get_xa_root(inode->i_sb, flags); | 156 | xaroot = open_xa_root(inode->i_sb, flags); |
107 | if (IS_ERR(xaroot)) | 157 | if (IS_ERR(xaroot)) |
108 | return xaroot; | 158 | return xaroot; |
109 | 159 | ||
110 | /* ok, we have xaroot open */ | ||
111 | snprintf(namebuf, sizeof(namebuf), "%X.%X", | 160 | snprintf(namebuf, sizeof(namebuf), "%X.%X", |
112 | le32_to_cpu(INODE_PKEY(inode)->k_objectid), | 161 | le32_to_cpu(INODE_PKEY(inode)->k_objectid), |
113 | inode->i_generation); | 162 | inode->i_generation); |
114 | xadir = lookup_one_len(namebuf, xaroot, strlen(namebuf)); | ||
115 | if (IS_ERR(xadir)) { | ||
116 | dput(xaroot); | ||
117 | return xadir; | ||
118 | } | ||
119 | |||
120 | if (!xadir->d_inode) { | ||
121 | int err; | ||
122 | if (flags == 0 || flags & XATTR_CREATE) { | ||
123 | /* Although there is nothing else trying to create this directory, | ||
124 | * another directory with the same hash may be created, so we need | ||
125 | * to protect against that */ | ||
126 | err = | ||
127 | xaroot->d_inode->i_op->mkdir(xaroot->d_inode, xadir, | ||
128 | 0700); | ||
129 | if (err) { | ||
130 | dput(xaroot); | ||
131 | dput(xadir); | ||
132 | return ERR_PTR(err); | ||
133 | } | ||
134 | } | ||
135 | if (!xadir->d_inode) { | ||
136 | dput(xaroot); | ||
137 | dput(xadir); | ||
138 | return ERR_PTR(-ENODATA); | ||
139 | } | ||
140 | } | ||
141 | 163 | ||
164 | xadir = lookup_or_create_dir(xaroot, namebuf, flags); | ||
142 | dput(xaroot); | 165 | dput(xaroot); |
143 | return xadir; | 166 | return xadir; |
167 | |||
144 | } | 168 | } |
145 | 169 | ||
146 | /* Returns a dentry corresponding to a specific extended attribute file | 170 | /* The following are side effects of other operations that aren't explicitly |
147 | * for the inode. If flags allow, the file is created. Otherwise, a | 171 | * modifying extended attributes. This includes operations such as permissions |
148 | * valid or negative dentry, or an error is returned. */ | 172 | * or ownership changes, object deletions, etc. */ |
149 | static struct dentry *get_xa_file_dentry(const struct inode *inode, | 173 | struct reiserfs_dentry_buf { |
150 | const char *name, int flags) | 174 | struct dentry *xadir; |
151 | { | 175 | int count; |
152 | struct dentry *xadir, *xafile; | 176 | struct dentry *dentries[8]; |
153 | int err = 0; | 177 | }; |
154 | 178 | ||
155 | xadir = open_xa_dir(inode, flags); | 179 | static int |
156 | if (IS_ERR(xadir)) { | 180 | fill_with_dentries(void *buf, const char *name, int namelen, loff_t offset, |
157 | return ERR_CAST(xadir); | 181 | u64 ino, unsigned int d_type) |
158 | } else if (!xadir->d_inode) { | 182 | { |
159 | dput(xadir); | 183 | struct reiserfs_dentry_buf *dbuf = buf; |
160 | return ERR_PTR(-ENODATA); | 184 | struct dentry *dentry; |
161 | } | ||
162 | 185 | ||
163 | xafile = lookup_one_len(name, xadir, strlen(name)); | 186 | if (dbuf->count == ARRAY_SIZE(dbuf->dentries)) |
164 | if (IS_ERR(xafile)) { | 187 | return -ENOSPC; |
165 | dput(xadir); | ||
166 | return ERR_CAST(xafile); | ||
167 | } | ||
168 | 188 | ||
169 | if (xafile->d_inode) { /* file exists */ | 189 | if (name[0] == '.' && (name[1] == '\0' || |
170 | if (flags & XATTR_CREATE) { | 190 | (name[1] == '.' && name[2] == '\0'))) |
171 | err = -EEXIST; | 191 | return 0; |
172 | dput(xafile); | ||
173 | goto out; | ||
174 | } | ||
175 | } else if (flags & XATTR_REPLACE || flags & FL_READONLY) { | ||
176 | goto out; | ||
177 | } else { | ||
178 | /* inode->i_mutex is down, so nothing else can try to create | ||
179 | * the same xattr */ | ||
180 | err = xadir->d_inode->i_op->create(xadir->d_inode, xafile, | ||
181 | 0700 | S_IFREG, NULL); | ||
182 | 192 | ||
183 | if (err) { | 193 | dentry = lookup_one_len(name, dbuf->xadir, namelen); |
184 | dput(xafile); | 194 | if (IS_ERR(dentry)) { |
185 | goto out; | 195 | return PTR_ERR(dentry); |
186 | } | 196 | } else if (!dentry->d_inode) { |
197 | /* A directory entry exists, but no file? */ | ||
198 | reiserfs_error(dentry->d_sb, "xattr-20003", | ||
199 | "Corrupted directory: xattr %s listed but " | ||
200 | "not found for file %s.\n", | ||
201 | dentry->d_name.name, dbuf->xadir->d_name.name); | ||
202 | dput(dentry); | ||
203 | return -EIO; | ||
187 | } | 204 | } |
188 | 205 | ||
189 | out: | 206 | dbuf->dentries[dbuf->count++] = dentry; |
190 | dput(xadir); | 207 | return 0; |
191 | if (err) | ||
192 | xafile = ERR_PTR(err); | ||
193 | else if (!xafile->d_inode) { | ||
194 | dput(xafile); | ||
195 | xafile = ERR_PTR(-ENODATA); | ||
196 | } | ||
197 | return xafile; | ||
198 | } | 208 | } |
199 | 209 | ||
200 | /* | 210 | static void |
201 | * this is very similar to fs/reiserfs/dir.c:reiserfs_readdir, but | 211 | cleanup_dentry_buf(struct reiserfs_dentry_buf *buf) |
202 | * we need to drop the path before calling the filldir struct. That | ||
203 | * would be a big performance hit to the non-xattr case, so I've copied | ||
204 | * the whole thing for now. --clm | ||
205 | * | ||
206 | * the big difference is that I go backwards through the directory, | ||
207 | * and don't mess with f->f_pos, but the idea is the same. Do some | ||
208 | * action on each and every entry in the directory. | ||
209 | * | ||
210 | * we're called with i_mutex held, so there are no worries about the directory | ||
211 | * changing underneath us. | ||
212 | */ | ||
213 | static int __xattr_readdir(struct inode *inode, void *dirent, filldir_t filldir) | ||
214 | { | 212 | { |
215 | struct cpu_key pos_key; /* key of current position in the directory (key of directory entry) */ | 213 | int i; |
216 | INITIALIZE_PATH(path_to_entry); | 214 | for (i = 0; i < buf->count; i++) |
217 | struct buffer_head *bh; | 215 | if (buf->dentries[i]) |
218 | int entry_num; | 216 | dput(buf->dentries[i]); |
219 | struct item_head *ih, tmp_ih; | 217 | } |
220 | int search_res; | 218 | |
221 | char *local_buf; | 219 | static int reiserfs_for_each_xattr(struct inode *inode, |
222 | loff_t next_pos; | 220 | int (*action)(struct dentry *, void *), |
223 | char small_buf[32]; /* avoid kmalloc if we can */ | 221 | void *data) |
224 | struct reiserfs_de_head *deh; | 222 | { |
225 | int d_reclen; | 223 | struct dentry *dir; |
226 | char *d_name; | 224 | int i, err = 0; |
227 | off_t d_off; | 225 | loff_t pos = 0; |
228 | ino_t d_ino; | 226 | struct reiserfs_dentry_buf buf = { |
229 | struct reiserfs_dir_entry de; | 227 | .count = 0, |
230 | 228 | }; | |
231 | /* form key for search the next directory entry using f_pos field of | ||
232 | file structure */ | ||
233 | next_pos = max_reiserfs_offset(inode); | ||
234 | |||
235 | while (1) { | ||
236 | research: | ||
237 | if (next_pos <= DOT_DOT_OFFSET) | ||
238 | break; | ||
239 | make_cpu_key(&pos_key, inode, next_pos, TYPE_DIRENTRY, 3); | ||
240 | |||
241 | search_res = | ||
242 | search_by_entry_key(inode->i_sb, &pos_key, &path_to_entry, | ||
243 | &de); | ||
244 | if (search_res == IO_ERROR) { | ||
245 | // FIXME: we could just skip part of directory which could | ||
246 | // not be read | ||
247 | pathrelse(&path_to_entry); | ||
248 | return -EIO; | ||
249 | } | ||
250 | 229 | ||
251 | if (search_res == NAME_NOT_FOUND) | 230 | /* Skip out, an xattr has no xattrs associated with it */ |
252 | de.de_entry_num--; | 231 | if (IS_PRIVATE(inode) || get_inode_sd_version(inode) == STAT_DATA_V1) |
232 | return 0; | ||
253 | 233 | ||
254 | set_de_name_and_namelen(&de); | 234 | dir = open_xa_dir(inode, XATTR_REPLACE); |
255 | entry_num = de.de_entry_num; | 235 | if (IS_ERR(dir)) { |
256 | deh = &(de.de_deh[entry_num]); | 236 | err = PTR_ERR(dir); |
237 | goto out; | ||
238 | } else if (!dir->d_inode) { | ||
239 | err = 0; | ||
240 | goto out_dir; | ||
241 | } | ||
257 | 242 | ||
258 | bh = de.de_bh; | 243 | mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_XATTR); |
259 | ih = de.de_ih; | 244 | buf.xadir = dir; |
245 | err = reiserfs_readdir_dentry(dir, &buf, fill_with_dentries, &pos); | ||
246 | while ((err == 0 || err == -ENOSPC) && buf.count) { | ||
247 | err = 0; | ||
260 | 248 | ||
261 | if (!is_direntry_le_ih(ih)) { | 249 | for (i = 0; i < buf.count && buf.dentries[i]; i++) { |
262 | reiserfs_warning(inode->i_sb, "not direntry %h", ih); | 250 | int lerr = 0; |
263 | break; | 251 | struct dentry *dentry = buf.dentries[i]; |
264 | } | ||
265 | copy_item_head(&tmp_ih, ih); | ||
266 | 252 | ||
267 | /* we must have found item, that is item of this directory, */ | 253 | if (err == 0 && !S_ISDIR(dentry->d_inode->i_mode)) |
268 | RFALSE(COMP_SHORT_KEYS(&(ih->ih_key), &pos_key), | 254 | lerr = action(dentry, data); |
269 | "vs-9000: found item %h does not match to dir we readdir %K", | ||
270 | ih, &pos_key); | ||
271 | 255 | ||
272 | if (deh_offset(deh) <= DOT_DOT_OFFSET) { | 256 | dput(dentry); |
273 | break; | 257 | buf.dentries[i] = NULL; |
258 | err = lerr ?: err; | ||
274 | } | 259 | } |
260 | buf.count = 0; | ||
261 | if (!err) | ||
262 | err = reiserfs_readdir_dentry(dir, &buf, | ||
263 | fill_with_dentries, &pos); | ||
264 | } | ||
265 | mutex_unlock(&dir->d_inode->i_mutex); | ||
275 | 266 | ||
276 | /* look for the previous entry in the directory */ | 267 | /* Clean up after a failed readdir */ |
277 | next_pos = deh_offset(deh) - 1; | 268 | cleanup_dentry_buf(&buf); |
278 | |||
279 | if (!de_visible(deh)) | ||
280 | /* it is hidden entry */ | ||
281 | continue; | ||
282 | 269 | ||
283 | d_reclen = entry_length(bh, ih, entry_num); | 270 | if (!err) { |
284 | d_name = B_I_DEH_ENTRY_FILE_NAME(bh, ih, deh); | 271 | /* We start a transaction here to avoid a ABBA situation |
285 | d_off = deh_offset(deh); | 272 | * between the xattr root's i_mutex and the journal lock. |
286 | d_ino = deh_objectid(deh); | 273 | * This doesn't incur much additional overhead since the |
274 | * new transaction will just nest inside the | ||
275 | * outer transaction. */ | ||
276 | int blocks = JOURNAL_PER_BALANCE_CNT * 2 + 2 + | ||
277 | 4 * REISERFS_QUOTA_TRANS_BLOCKS(inode->i_sb); | ||
278 | struct reiserfs_transaction_handle th; | ||
279 | err = journal_begin(&th, inode->i_sb, blocks); | ||
280 | if (!err) { | ||
281 | int jerror; | ||
282 | mutex_lock_nested(&dir->d_parent->d_inode->i_mutex, | ||
283 | I_MUTEX_XATTR); | ||
284 | err = action(dir, data); | ||
285 | jerror = journal_end(&th, inode->i_sb, blocks); | ||
286 | mutex_unlock(&dir->d_parent->d_inode->i_mutex); | ||
287 | err = jerror ?: err; | ||
288 | } | ||
289 | } | ||
290 | out_dir: | ||
291 | dput(dir); | ||
292 | out: | ||
293 | /* -ENODATA isn't an error */ | ||
294 | if (err == -ENODATA) | ||
295 | err = 0; | ||
296 | return err; | ||
297 | } | ||
287 | 298 | ||
288 | if (!d_name[d_reclen - 1]) | 299 | static int delete_one_xattr(struct dentry *dentry, void *data) |
289 | d_reclen = strlen(d_name); | 300 | { |
301 | struct inode *dir = dentry->d_parent->d_inode; | ||
290 | 302 | ||
291 | if (d_reclen > REISERFS_MAX_NAME(inode->i_sb->s_blocksize)) { | 303 | /* This is the xattr dir, handle specially. */ |
292 | /* too big to send back to VFS */ | 304 | if (S_ISDIR(dentry->d_inode->i_mode)) |
293 | continue; | 305 | return xattr_rmdir(dir, dentry); |
294 | } | ||
295 | 306 | ||
296 | /* Ignore the .reiserfs_priv entry */ | 307 | return xattr_unlink(dir, dentry); |
297 | if (reiserfs_xattrs(inode->i_sb) && | 308 | } |
298 | !old_format_only(inode->i_sb) && | ||
299 | deh_objectid(deh) == | ||
300 | le32_to_cpu(INODE_PKEY | ||
301 | (REISERFS_SB(inode->i_sb)->priv_root->d_inode)-> | ||
302 | k_objectid)) | ||
303 | continue; | ||
304 | |||
305 | if (d_reclen <= 32) { | ||
306 | local_buf = small_buf; | ||
307 | } else { | ||
308 | local_buf = kmalloc(d_reclen, GFP_NOFS); | ||
309 | if (!local_buf) { | ||
310 | pathrelse(&path_to_entry); | ||
311 | return -ENOMEM; | ||
312 | } | ||
313 | if (item_moved(&tmp_ih, &path_to_entry)) { | ||
314 | kfree(local_buf); | ||
315 | 309 | ||
316 | /* sigh, must retry. Do this same offset again */ | 310 | static int chown_one_xattr(struct dentry *dentry, void *data) |
317 | next_pos = d_off; | 311 | { |
318 | goto research; | 312 | struct iattr *attrs = data; |
319 | } | 313 | return reiserfs_setattr(dentry, attrs); |
320 | } | 314 | } |
321 | 315 | ||
322 | // Note, that we copy name to user space via temporary | 316 | /* No i_mutex, but the inode is unconnected. */ |
323 | // buffer (local_buf) because filldir will block if | 317 | int reiserfs_delete_xattrs(struct inode *inode) |
324 | // user space buffer is swapped out. At that time | 318 | { |
325 | // entry can move to somewhere else | 319 | int err = reiserfs_for_each_xattr(inode, delete_one_xattr, NULL); |
326 | memcpy(local_buf, d_name, d_reclen); | 320 | if (err) |
327 | 321 | reiserfs_warning(inode->i_sb, "jdm-20004", | |
328 | /* the filldir function might need to start transactions, | 322 | "Couldn't delete all xattrs (%d)\n", err); |
329 | * or do who knows what. Release the path now that we've | 323 | return err; |
330 | * copied all the important stuff out of the deh | 324 | } |
331 | */ | ||
332 | pathrelse(&path_to_entry); | ||
333 | |||
334 | if (filldir(dirent, local_buf, d_reclen, d_off, d_ino, | ||
335 | DT_UNKNOWN) < 0) { | ||
336 | if (local_buf != small_buf) { | ||
337 | kfree(local_buf); | ||
338 | } | ||
339 | goto end; | ||
340 | } | ||
341 | if (local_buf != small_buf) { | ||
342 | kfree(local_buf); | ||
343 | } | ||
344 | } /* while */ | ||
345 | 325 | ||
346 | end: | 326 | /* inode->i_mutex: down */ |
347 | pathrelse(&path_to_entry); | 327 | int reiserfs_chown_xattrs(struct inode *inode, struct iattr *attrs) |
348 | return 0; | 328 | { |
329 | int err = reiserfs_for_each_xattr(inode, chown_one_xattr, attrs); | ||
330 | if (err) | ||
331 | reiserfs_warning(inode->i_sb, "jdm-20007", | ||
332 | "Couldn't chown all xattrs (%d)\n", err); | ||
333 | return err; | ||
349 | } | 334 | } |
350 | 335 | ||
351 | /* | 336 | #ifdef CONFIG_REISERFS_FS_XATTR |
352 | * this could be done with dedicated readdir ops for the xattr files, | 337 | /* Returns a dentry corresponding to a specific extended attribute file |
353 | * but I want to get something working asap | 338 | * for the inode. If flags allow, the file is created. Otherwise, a |
354 | * this is stolen from vfs_readdir | 339 | * valid or negative dentry, or an error is returned. */ |
355 | * | 340 | static struct dentry *xattr_lookup(struct inode *inode, const char *name, |
356 | */ | 341 | int flags) |
357 | static | ||
358 | int xattr_readdir(struct inode *inode, filldir_t filler, void *buf) | ||
359 | { | 342 | { |
360 | int res = -ENOENT; | 343 | struct dentry *xadir, *xafile; |
361 | mutex_lock_nested(&inode->i_mutex, I_MUTEX_XATTR); | 344 | int err = 0; |
362 | if (!IS_DEADDIR(inode)) { | 345 | |
363 | lock_kernel(); | 346 | xadir = open_xa_dir(inode, flags); |
364 | res = __xattr_readdir(inode, buf, filler); | 347 | if (IS_ERR(xadir)) |
365 | unlock_kernel(); | 348 | return ERR_CAST(xadir); |
349 | |||
350 | xafile = lookup_one_len(name, xadir, strlen(name)); | ||
351 | if (IS_ERR(xafile)) { | ||
352 | err = PTR_ERR(xafile); | ||
353 | goto out; | ||
366 | } | 354 | } |
367 | mutex_unlock(&inode->i_mutex); | 355 | |
368 | return res; | 356 | if (xafile->d_inode && (flags & XATTR_CREATE)) |
357 | err = -EEXIST; | ||
358 | |||
359 | if (!xafile->d_inode) { | ||
360 | err = -ENODATA; | ||
361 | if (xattr_may_create(flags)) { | ||
362 | mutex_lock_nested(&xadir->d_inode->i_mutex, | ||
363 | I_MUTEX_XATTR); | ||
364 | err = xattr_create(xadir->d_inode, xafile, | ||
365 | 0700|S_IFREG); | ||
366 | mutex_unlock(&xadir->d_inode->i_mutex); | ||
367 | } | ||
368 | } | ||
369 | |||
370 | if (err) | ||
371 | dput(xafile); | ||
372 | out: | ||
373 | dput(xadir); | ||
374 | if (err) | ||
375 | return ERR_PTR(err); | ||
376 | return xafile; | ||
369 | } | 377 | } |
370 | 378 | ||
371 | /* Internal operations on file data */ | 379 | /* Internal operations on file data */ |
@@ -375,14 +383,14 @@ static inline void reiserfs_put_page(struct page *page) | |||
375 | page_cache_release(page); | 383 | page_cache_release(page); |
376 | } | 384 | } |
377 | 385 | ||
378 | static struct page *reiserfs_get_page(struct inode *dir, unsigned long n) | 386 | static struct page *reiserfs_get_page(struct inode *dir, size_t n) |
379 | { | 387 | { |
380 | struct address_space *mapping = dir->i_mapping; | 388 | struct address_space *mapping = dir->i_mapping; |
381 | struct page *page; | 389 | struct page *page; |
382 | /* We can deadlock if we try to free dentries, | 390 | /* We can deadlock if we try to free dentries, |
383 | and an unlink/rmdir has just occured - GFP_NOFS avoids this */ | 391 | and an unlink/rmdir has just occured - GFP_NOFS avoids this */ |
384 | mapping_set_gfp_mask(mapping, GFP_NOFS); | 392 | mapping_set_gfp_mask(mapping, GFP_NOFS); |
385 | page = read_mapping_page(mapping, n, NULL); | 393 | page = read_mapping_page(mapping, n >> PAGE_CACHE_SHIFT, NULL); |
386 | if (!IS_ERR(page)) { | 394 | if (!IS_ERR(page)) { |
387 | kmap(page); | 395 | kmap(page); |
388 | if (PageError(page)) | 396 | if (PageError(page)) |
@@ -405,6 +413,45 @@ int reiserfs_commit_write(struct file *f, struct page *page, | |||
405 | int reiserfs_prepare_write(struct file *f, struct page *page, | 413 | int reiserfs_prepare_write(struct file *f, struct page *page, |
406 | unsigned from, unsigned to); | 414 | unsigned from, unsigned to); |
407 | 415 | ||
416 | static void update_ctime(struct inode *inode) | ||
417 | { | ||
418 | struct timespec now = current_fs_time(inode->i_sb); | ||
419 | if (hlist_unhashed(&inode->i_hash) || !inode->i_nlink || | ||
420 | timespec_equal(&inode->i_ctime, &now)) | ||
421 | return; | ||
422 | |||
423 | inode->i_ctime = CURRENT_TIME_SEC; | ||
424 | mark_inode_dirty(inode); | ||
425 | } | ||
426 | |||
427 | static int lookup_and_delete_xattr(struct inode *inode, const char *name) | ||
428 | { | ||
429 | int err = 0; | ||
430 | struct dentry *dentry, *xadir; | ||
431 | |||
432 | xadir = open_xa_dir(inode, XATTR_REPLACE); | ||
433 | if (IS_ERR(xadir)) | ||
434 | return PTR_ERR(xadir); | ||
435 | |||
436 | dentry = lookup_one_len(name, xadir, strlen(name)); | ||
437 | if (IS_ERR(dentry)) { | ||
438 | err = PTR_ERR(dentry); | ||
439 | goto out_dput; | ||
440 | } | ||
441 | |||
442 | if (dentry->d_inode) { | ||
443 | mutex_lock_nested(&xadir->d_inode->i_mutex, I_MUTEX_XATTR); | ||
444 | err = xattr_unlink(xadir->d_inode, dentry); | ||
445 | mutex_unlock(&xadir->d_inode->i_mutex); | ||
446 | update_ctime(inode); | ||
447 | } | ||
448 | |||
449 | dput(dentry); | ||
450 | out_dput: | ||
451 | dput(xadir); | ||
452 | return err; | ||
453 | } | ||
454 | |||
408 | 455 | ||
409 | /* Generic extended attribute operations that can be used by xa plugins */ | 456 | /* Generic extended attribute operations that can be used by xa plugins */ |
410 | 457 | ||
@@ -412,58 +459,32 @@ int reiserfs_prepare_write(struct file *f, struct page *page, | |||
412 | * inode->i_mutex: down | 459 | * inode->i_mutex: down |
413 | */ | 460 | */ |
414 | int | 461 | int |
415 | reiserfs_xattr_set(struct inode *inode, const char *name, const void *buffer, | 462 | reiserfs_xattr_set_handle(struct reiserfs_transaction_handle *th, |
416 | size_t buffer_size, int flags) | 463 | struct inode *inode, const char *name, |
464 | const void *buffer, size_t buffer_size, int flags) | ||
417 | { | 465 | { |
418 | int err = 0; | 466 | int err = 0; |
419 | struct dentry *dentry; | 467 | struct dentry *dentry; |
420 | struct page *page; | 468 | struct page *page; |
421 | char *data; | 469 | char *data; |
422 | struct address_space *mapping; | ||
423 | size_t file_pos = 0; | 470 | size_t file_pos = 0; |
424 | size_t buffer_pos = 0; | 471 | size_t buffer_pos = 0; |
425 | struct inode *xinode; | 472 | size_t new_size; |
426 | struct iattr newattrs; | ||
427 | __u32 xahash = 0; | 473 | __u32 xahash = 0; |
428 | 474 | ||
429 | if (get_inode_sd_version(inode) == STAT_DATA_V1) | 475 | if (get_inode_sd_version(inode) == STAT_DATA_V1) |
430 | return -EOPNOTSUPP; | 476 | return -EOPNOTSUPP; |
431 | 477 | ||
432 | /* Empty xattrs are ok, they're just empty files, no hash */ | 478 | if (!buffer) |
433 | if (buffer && buffer_size) | 479 | return lookup_and_delete_xattr(inode, name); |
434 | xahash = xattr_hash(buffer, buffer_size); | ||
435 | 480 | ||
436 | open_file: | 481 | dentry = xattr_lookup(inode, name, flags); |
437 | dentry = get_xa_file_dentry(inode, name, flags); | 482 | if (IS_ERR(dentry)) |
438 | if (IS_ERR(dentry)) { | 483 | return PTR_ERR(dentry); |
439 | err = PTR_ERR(dentry); | ||
440 | goto out; | ||
441 | } | ||
442 | |||
443 | xinode = dentry->d_inode; | ||
444 | REISERFS_I(inode)->i_flags |= i_has_xattr_dir; | ||
445 | 484 | ||
446 | /* we need to copy it off.. */ | 485 | down_write(&REISERFS_I(inode)->i_xattr_sem); |
447 | if (xinode->i_nlink > 1) { | ||
448 | dput(dentry); | ||
449 | err = reiserfs_xattr_del(inode, name); | ||
450 | if (err < 0) | ||
451 | goto out; | ||
452 | /* We just killed the old one, we're not replacing anymore */ | ||
453 | if (flags & XATTR_REPLACE) | ||
454 | flags &= ~XATTR_REPLACE; | ||
455 | goto open_file; | ||
456 | } | ||
457 | 486 | ||
458 | /* Resize it so we're ok to write there */ | 487 | xahash = xattr_hash(buffer, buffer_size); |
459 | newattrs.ia_size = buffer_size; | ||
460 | newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME; | ||
461 | mutex_lock_nested(&xinode->i_mutex, I_MUTEX_XATTR); | ||
462 | err = notify_change(dentry, &newattrs); | ||
463 | if (err) | ||
464 | goto out_filp; | ||
465 | |||
466 | mapping = xinode->i_mapping; | ||
467 | while (buffer_pos < buffer_size || buffer_pos == 0) { | 488 | while (buffer_pos < buffer_size || buffer_pos == 0) { |
468 | size_t chunk; | 489 | size_t chunk; |
469 | size_t skip = 0; | 490 | size_t skip = 0; |
@@ -473,10 +494,10 @@ reiserfs_xattr_set(struct inode *inode, const char *name, const void *buffer, | |||
473 | else | 494 | else |
474 | chunk = buffer_size - buffer_pos; | 495 | chunk = buffer_size - buffer_pos; |
475 | 496 | ||
476 | page = reiserfs_get_page(xinode, file_pos >> PAGE_CACHE_SHIFT); | 497 | page = reiserfs_get_page(dentry->d_inode, file_pos); |
477 | if (IS_ERR(page)) { | 498 | if (IS_ERR(page)) { |
478 | err = PTR_ERR(page); | 499 | err = PTR_ERR(page); |
479 | goto out_filp; | 500 | goto out_unlock; |
480 | } | 501 | } |
481 | 502 | ||
482 | lock_page(page); | 503 | lock_page(page); |
@@ -510,28 +531,61 @@ reiserfs_xattr_set(struct inode *inode, const char *name, const void *buffer, | |||
510 | break; | 531 | break; |
511 | } | 532 | } |
512 | 533 | ||
513 | /* We can't mark the inode dirty if it's not hashed. This is the case | 534 | new_size = buffer_size + sizeof(struct reiserfs_xattr_header); |
514 | * when we're inheriting the default ACL. If we dirty it, the inode | 535 | if (!err && new_size < i_size_read(dentry->d_inode)) { |
515 | * gets marked dirty, but won't (ever) make it onto the dirty list until | 536 | struct iattr newattrs = { |
516 | * it's synced explicitly to clear I_DIRTY. This is bad. */ | 537 | .ia_ctime = current_fs_time(inode->i_sb), |
517 | if (!hlist_unhashed(&inode->i_hash)) { | 538 | .ia_size = buffer_size, |
518 | inode->i_ctime = CURRENT_TIME_SEC; | 539 | .ia_valid = ATTR_SIZE | ATTR_CTIME, |
519 | mark_inode_dirty(inode); | 540 | }; |
541 | mutex_lock_nested(&dentry->d_inode->i_mutex, I_MUTEX_XATTR); | ||
542 | down_write(&dentry->d_inode->i_alloc_sem); | ||
543 | err = reiserfs_setattr(dentry, &newattrs); | ||
544 | up_write(&dentry->d_inode->i_alloc_sem); | ||
545 | mutex_unlock(&dentry->d_inode->i_mutex); | ||
546 | } else | ||
547 | update_ctime(inode); | ||
548 | out_unlock: | ||
549 | up_write(&REISERFS_I(inode)->i_xattr_sem); | ||
550 | dput(dentry); | ||
551 | return err; | ||
552 | } | ||
553 | |||
554 | /* We need to start a transaction to maintain lock ordering */ | ||
555 | int reiserfs_xattr_set(struct inode *inode, const char *name, | ||
556 | const void *buffer, size_t buffer_size, int flags) | ||
557 | { | ||
558 | |||
559 | struct reiserfs_transaction_handle th; | ||
560 | int error, error2; | ||
561 | size_t jbegin_count = reiserfs_xattr_nblocks(inode, buffer_size); | ||
562 | |||
563 | if (!(flags & XATTR_REPLACE)) | ||
564 | jbegin_count += reiserfs_xattr_jcreate_nblocks(inode); | ||
565 | |||
566 | reiserfs_write_lock(inode->i_sb); | ||
567 | error = journal_begin(&th, inode->i_sb, jbegin_count); | ||
568 | if (error) { | ||
569 | reiserfs_write_unlock(inode->i_sb); | ||
570 | return error; | ||
520 | } | 571 | } |
521 | 572 | ||
522 | out_filp: | 573 | error = reiserfs_xattr_set_handle(&th, inode, name, |
523 | mutex_unlock(&xinode->i_mutex); | 574 | buffer, buffer_size, flags); |
524 | dput(dentry); | ||
525 | 575 | ||
526 | out: | 576 | error2 = journal_end(&th, inode->i_sb, jbegin_count); |
527 | return err; | 577 | if (error == 0) |
578 | error = error2; | ||
579 | reiserfs_write_unlock(inode->i_sb); | ||
580 | |||
581 | return error; | ||
528 | } | 582 | } |
529 | 583 | ||
530 | /* | 584 | /* |
531 | * inode->i_mutex: down | 585 | * inode->i_mutex: down |
532 | */ | 586 | */ |
533 | int | 587 | int |
534 | reiserfs_xattr_get(const struct inode *inode, const char *name, void *buffer, | 588 | reiserfs_xattr_get(struct inode *inode, const char *name, void *buffer, |
535 | size_t buffer_size) | 589 | size_t buffer_size) |
536 | { | 590 | { |
537 | ssize_t err = 0; | 591 | ssize_t err = 0; |
@@ -540,7 +594,6 @@ reiserfs_xattr_get(const struct inode *inode, const char *name, void *buffer, | |||
540 | size_t file_pos = 0; | 594 | size_t file_pos = 0; |
541 | size_t buffer_pos = 0; | 595 | size_t buffer_pos = 0; |
542 | struct page *page; | 596 | struct page *page; |
543 | struct inode *xinode; | ||
544 | __u32 hash = 0; | 597 | __u32 hash = 0; |
545 | 598 | ||
546 | if (name == NULL) | 599 | if (name == NULL) |
@@ -551,25 +604,25 @@ reiserfs_xattr_get(const struct inode *inode, const char *name, void *buffer, | |||
551 | if (get_inode_sd_version(inode) == STAT_DATA_V1) | 604 | if (get_inode_sd_version(inode) == STAT_DATA_V1) |
552 | return -EOPNOTSUPP; | 605 | return -EOPNOTSUPP; |
553 | 606 | ||
554 | dentry = get_xa_file_dentry(inode, name, FL_READONLY); | 607 | dentry = xattr_lookup(inode, name, XATTR_REPLACE); |
555 | if (IS_ERR(dentry)) { | 608 | if (IS_ERR(dentry)) { |
556 | err = PTR_ERR(dentry); | 609 | err = PTR_ERR(dentry); |
557 | goto out; | 610 | goto out; |
558 | } | 611 | } |
559 | 612 | ||
560 | xinode = dentry->d_inode; | 613 | down_read(&REISERFS_I(inode)->i_xattr_sem); |
561 | isize = xinode->i_size; | 614 | |
562 | REISERFS_I(inode)->i_flags |= i_has_xattr_dir; | 615 | isize = i_size_read(dentry->d_inode); |
563 | 616 | ||
564 | /* Just return the size needed */ | 617 | /* Just return the size needed */ |
565 | if (buffer == NULL) { | 618 | if (buffer == NULL) { |
566 | err = isize - sizeof(struct reiserfs_xattr_header); | 619 | err = isize - sizeof(struct reiserfs_xattr_header); |
567 | goto out_dput; | 620 | goto out_unlock; |
568 | } | 621 | } |
569 | 622 | ||
570 | if (buffer_size < isize - sizeof(struct reiserfs_xattr_header)) { | 623 | if (buffer_size < isize - sizeof(struct reiserfs_xattr_header)) { |
571 | err = -ERANGE; | 624 | err = -ERANGE; |
572 | goto out_dput; | 625 | goto out_unlock; |
573 | } | 626 | } |
574 | 627 | ||
575 | while (file_pos < isize) { | 628 | while (file_pos < isize) { |
@@ -581,10 +634,10 @@ reiserfs_xattr_get(const struct inode *inode, const char *name, void *buffer, | |||
581 | else | 634 | else |
582 | chunk = isize - file_pos; | 635 | chunk = isize - file_pos; |
583 | 636 | ||
584 | page = reiserfs_get_page(xinode, file_pos >> PAGE_CACHE_SHIFT); | 637 | page = reiserfs_get_page(dentry->d_inode, file_pos); |
585 | if (IS_ERR(page)) { | 638 | if (IS_ERR(page)) { |
586 | err = PTR_ERR(page); | 639 | err = PTR_ERR(page); |
587 | goto out_dput; | 640 | goto out_unlock; |
588 | } | 641 | } |
589 | 642 | ||
590 | lock_page(page); | 643 | lock_page(page); |
@@ -598,12 +651,12 @@ reiserfs_xattr_get(const struct inode *inode, const char *name, void *buffer, | |||
598 | if (rxh->h_magic != cpu_to_le32(REISERFS_XATTR_MAGIC)) { | 651 | if (rxh->h_magic != cpu_to_le32(REISERFS_XATTR_MAGIC)) { |
599 | unlock_page(page); | 652 | unlock_page(page); |
600 | reiserfs_put_page(page); | 653 | reiserfs_put_page(page); |
601 | reiserfs_warning(inode->i_sb, | 654 | reiserfs_warning(inode->i_sb, "jdm-20001", |
602 | "Invalid magic for xattr (%s) " | 655 | "Invalid magic for xattr (%s) " |
603 | "associated with %k", name, | 656 | "associated with %k", name, |
604 | INODE_PKEY(inode)); | 657 | INODE_PKEY(inode)); |
605 | err = -EIO; | 658 | err = -EIO; |
606 | goto out_dput; | 659 | goto out_unlock; |
607 | } | 660 | } |
608 | hash = le32_to_cpu(rxh->h_hash); | 661 | hash = le32_to_cpu(rxh->h_hash); |
609 | } | 662 | } |
@@ -618,256 +671,83 @@ reiserfs_xattr_get(const struct inode *inode, const char *name, void *buffer, | |||
618 | 671 | ||
619 | if (xattr_hash(buffer, isize - sizeof(struct reiserfs_xattr_header)) != | 672 | if (xattr_hash(buffer, isize - sizeof(struct reiserfs_xattr_header)) != |
620 | hash) { | 673 | hash) { |
621 | reiserfs_warning(inode->i_sb, | 674 | reiserfs_warning(inode->i_sb, "jdm-20002", |
622 | "Invalid hash for xattr (%s) associated " | 675 | "Invalid hash for xattr (%s) associated " |
623 | "with %k", name, INODE_PKEY(inode)); | 676 | "with %k", name, INODE_PKEY(inode)); |
624 | err = -EIO; | 677 | err = -EIO; |
625 | } | 678 | } |
626 | 679 | ||
627 | out_dput: | 680 | out_unlock: |
681 | up_read(&REISERFS_I(inode)->i_xattr_sem); | ||
628 | dput(dentry); | 682 | dput(dentry); |
629 | 683 | ||
630 | out: | 684 | out: |
631 | return err; | ||
632 | } | ||
633 | |||
634 | static int | ||
635 | __reiserfs_xattr_del(struct dentry *xadir, const char *name, int namelen) | ||
636 | { | ||
637 | struct dentry *dentry; | ||
638 | struct inode *dir = xadir->d_inode; | ||
639 | int err = 0; | ||
640 | |||
641 | dentry = lookup_one_len(name, xadir, namelen); | ||
642 | if (IS_ERR(dentry)) { | ||
643 | err = PTR_ERR(dentry); | ||
644 | goto out; | ||
645 | } else if (!dentry->d_inode) { | ||
646 | err = -ENODATA; | ||
647 | goto out_file; | ||
648 | } | ||
649 | |||
650 | /* Skip directories.. */ | ||
651 | if (S_ISDIR(dentry->d_inode->i_mode)) | ||
652 | goto out_file; | ||
653 | |||
654 | if (!is_reiserfs_priv_object(dentry->d_inode)) { | ||
655 | reiserfs_warning(dir->i_sb, "OID %08x [%.*s/%.*s] doesn't have " | ||
656 | "priv flag set [parent is %sset].", | ||
657 | le32_to_cpu(INODE_PKEY(dentry->d_inode)-> | ||
658 | k_objectid), xadir->d_name.len, | ||
659 | xadir->d_name.name, namelen, name, | ||
660 | is_reiserfs_priv_object(xadir-> | ||
661 | d_inode) ? "" : | ||
662 | "not "); | ||
663 | dput(dentry); | ||
664 | return -EIO; | ||
665 | } | ||
666 | |||
667 | err = dir->i_op->unlink(dir, dentry); | ||
668 | if (!err) | ||
669 | d_delete(dentry); | ||
670 | |||
671 | out_file: | ||
672 | dput(dentry); | ||
673 | |||
674 | out: | ||
675 | return err; | ||
676 | } | ||
677 | |||
678 | int reiserfs_xattr_del(struct inode *inode, const char *name) | ||
679 | { | ||
680 | struct dentry *dir; | ||
681 | int err; | ||
682 | |||
683 | dir = open_xa_dir(inode, FL_READONLY); | ||
684 | if (IS_ERR(dir)) { | ||
685 | err = PTR_ERR(dir); | ||
686 | goto out; | ||
687 | } | ||
688 | |||
689 | err = __reiserfs_xattr_del(dir, name, strlen(name)); | ||
690 | dput(dir); | ||
691 | |||
692 | if (!err) { | ||
693 | inode->i_ctime = CURRENT_TIME_SEC; | ||
694 | mark_inode_dirty(inode); | ||
695 | } | ||
696 | |||
697 | out: | ||
698 | return err; | 685 | return err; |
699 | } | 686 | } |
700 | 687 | ||
701 | /* The following are side effects of other operations that aren't explicitly | 688 | /* Actual operations that are exported to VFS-land */ |
702 | * modifying extended attributes. This includes operations such as permissions | 689 | struct xattr_handler *reiserfs_xattr_handlers[] = { |
703 | * or ownership changes, object deletions, etc. */ | 690 | &reiserfs_xattr_user_handler, |
704 | 691 | &reiserfs_xattr_trusted_handler, | |
705 | static int | 692 | #ifdef CONFIG_REISERFS_FS_SECURITY |
706 | reiserfs_delete_xattrs_filler(void *buf, const char *name, int namelen, | 693 | &reiserfs_xattr_security_handler, |
707 | loff_t offset, u64 ino, unsigned int d_type) | 694 | #endif |
708 | { | 695 | #ifdef CONFIG_REISERFS_FS_POSIX_ACL |
709 | struct dentry *xadir = (struct dentry *)buf; | 696 | &reiserfs_posix_acl_access_handler, |
710 | 697 | &reiserfs_posix_acl_default_handler, | |
711 | return __reiserfs_xattr_del(xadir, name, namelen); | 698 | #endif |
712 | 699 | NULL | |
713 | } | ||
714 | |||
715 | /* This is called w/ inode->i_mutex downed */ | ||
716 | int reiserfs_delete_xattrs(struct inode *inode) | ||
717 | { | ||
718 | struct dentry *dir, *root; | ||
719 | int err = 0; | ||
720 | |||
721 | /* Skip out, an xattr has no xattrs associated with it */ | ||
722 | if (is_reiserfs_priv_object(inode) || | ||
723 | get_inode_sd_version(inode) == STAT_DATA_V1 || | ||
724 | !reiserfs_xattrs(inode->i_sb)) { | ||
725 | return 0; | ||
726 | } | ||
727 | reiserfs_read_lock_xattrs(inode->i_sb); | ||
728 | dir = open_xa_dir(inode, FL_READONLY); | ||
729 | reiserfs_read_unlock_xattrs(inode->i_sb); | ||
730 | if (IS_ERR(dir)) { | ||
731 | err = PTR_ERR(dir); | ||
732 | goto out; | ||
733 | } else if (!dir->d_inode) { | ||
734 | dput(dir); | ||
735 | return 0; | ||
736 | } | ||
737 | |||
738 | lock_kernel(); | ||
739 | err = xattr_readdir(dir->d_inode, reiserfs_delete_xattrs_filler, dir); | ||
740 | if (err) { | ||
741 | unlock_kernel(); | ||
742 | goto out_dir; | ||
743 | } | ||
744 | |||
745 | /* Leftovers besides . and .. -- that's not good. */ | ||
746 | if (dir->d_inode->i_nlink <= 2) { | ||
747 | root = get_xa_root(inode->i_sb, XATTR_REPLACE); | ||
748 | reiserfs_write_lock_xattrs(inode->i_sb); | ||
749 | err = vfs_rmdir(root->d_inode, dir); | ||
750 | reiserfs_write_unlock_xattrs(inode->i_sb); | ||
751 | dput(root); | ||
752 | } else { | ||
753 | reiserfs_warning(inode->i_sb, | ||
754 | "Couldn't remove all entries in directory"); | ||
755 | } | ||
756 | unlock_kernel(); | ||
757 | |||
758 | out_dir: | ||
759 | dput(dir); | ||
760 | |||
761 | out: | ||
762 | if (!err) | ||
763 | REISERFS_I(inode)->i_flags = | ||
764 | REISERFS_I(inode)->i_flags & ~i_has_xattr_dir; | ||
765 | return err; | ||
766 | } | ||
767 | |||
768 | struct reiserfs_chown_buf { | ||
769 | struct inode *inode; | ||
770 | struct dentry *xadir; | ||
771 | struct iattr *attrs; | ||
772 | }; | 700 | }; |
773 | 701 | ||
774 | /* XXX: If there is a better way to do this, I'd love to hear about it */ | 702 | /* |
775 | static int | 703 | * In order to implement different sets of xattr operations for each xattr |
776 | reiserfs_chown_xattrs_filler(void *buf, const char *name, int namelen, | 704 | * prefix with the generic xattr API, a filesystem should create a |
777 | loff_t offset, u64 ino, unsigned int d_type) | 705 | * null-terminated array of struct xattr_handler (one for each prefix) and |
778 | { | 706 | * hang a pointer to it off of the s_xattr field of the superblock. |
779 | struct reiserfs_chown_buf *chown_buf = (struct reiserfs_chown_buf *)buf; | 707 | * |
780 | struct dentry *xafile, *xadir = chown_buf->xadir; | 708 | * The generic_fooxattr() functions will use this list to dispatch xattr |
781 | struct iattr *attrs = chown_buf->attrs; | 709 | * operations to the correct xattr_handler. |
782 | int err = 0; | 710 | */ |
783 | 711 | #define for_each_xattr_handler(handlers, handler) \ | |
784 | xafile = lookup_one_len(name, xadir, namelen); | 712 | for ((handler) = *(handlers)++; \ |
785 | if (IS_ERR(xafile)) | 713 | (handler) != NULL; \ |
786 | return PTR_ERR(xafile); | 714 | (handler) = *(handlers)++) |
787 | else if (!xafile->d_inode) { | ||
788 | dput(xafile); | ||
789 | return -ENODATA; | ||
790 | } | ||
791 | |||
792 | if (!S_ISDIR(xafile->d_inode->i_mode)) | ||
793 | err = notify_change(xafile, attrs); | ||
794 | dput(xafile); | ||
795 | |||
796 | return err; | ||
797 | } | ||
798 | 715 | ||
799 | int reiserfs_chown_xattrs(struct inode *inode, struct iattr *attrs) | 716 | /* This is the implementation for the xattr plugin infrastructure */ |
717 | static inline struct xattr_handler * | ||
718 | find_xattr_handler_prefix(struct xattr_handler **handlers, | ||
719 | const char *name) | ||
800 | { | 720 | { |
801 | struct dentry *dir; | 721 | struct xattr_handler *xah; |
802 | int err = 0; | ||
803 | struct reiserfs_chown_buf buf; | ||
804 | unsigned int ia_valid = attrs->ia_valid; | ||
805 | 722 | ||
806 | /* Skip out, an xattr has no xattrs associated with it */ | 723 | if (!handlers) |
807 | if (is_reiserfs_priv_object(inode) || | 724 | return NULL; |
808 | get_inode_sd_version(inode) == STAT_DATA_V1 || | ||
809 | !reiserfs_xattrs(inode->i_sb)) { | ||
810 | return 0; | ||
811 | } | ||
812 | reiserfs_read_lock_xattrs(inode->i_sb); | ||
813 | dir = open_xa_dir(inode, FL_READONLY); | ||
814 | reiserfs_read_unlock_xattrs(inode->i_sb); | ||
815 | if (IS_ERR(dir)) { | ||
816 | if (PTR_ERR(dir) != -ENODATA) | ||
817 | err = PTR_ERR(dir); | ||
818 | goto out; | ||
819 | } else if (!dir->d_inode) { | ||
820 | dput(dir); | ||
821 | goto out; | ||
822 | } | ||
823 | 725 | ||
824 | lock_kernel(); | 726 | for_each_xattr_handler(handlers, xah) { |
825 | 727 | if (strncmp(xah->prefix, name, strlen(xah->prefix)) == 0) | |
826 | attrs->ia_valid &= (ATTR_UID | ATTR_GID | ATTR_CTIME); | 728 | break; |
827 | buf.xadir = dir; | ||
828 | buf.attrs = attrs; | ||
829 | buf.inode = inode; | ||
830 | |||
831 | err = xattr_readdir(dir->d_inode, reiserfs_chown_xattrs_filler, &buf); | ||
832 | if (err) { | ||
833 | unlock_kernel(); | ||
834 | goto out_dir; | ||
835 | } | 729 | } |
836 | 730 | ||
837 | err = notify_change(dir, attrs); | 731 | return xah; |
838 | unlock_kernel(); | ||
839 | |||
840 | out_dir: | ||
841 | dput(dir); | ||
842 | |||
843 | out: | ||
844 | attrs->ia_valid = ia_valid; | ||
845 | return err; | ||
846 | } | 732 | } |
847 | 733 | ||
848 | /* Actual operations that are exported to VFS-land */ | ||
849 | 734 | ||
850 | /* | 735 | /* |
851 | * Inode operation getxattr() | 736 | * Inode operation getxattr() |
852 | * Preliminary locking: we down dentry->d_inode->i_mutex | ||
853 | */ | 737 | */ |
854 | ssize_t | 738 | ssize_t |
855 | reiserfs_getxattr(struct dentry * dentry, const char *name, void *buffer, | 739 | reiserfs_getxattr(struct dentry * dentry, const char *name, void *buffer, |
856 | size_t size) | 740 | size_t size) |
857 | { | 741 | { |
858 | struct reiserfs_xattr_handler *xah = find_xattr_handler_prefix(name); | 742 | struct inode *inode = dentry->d_inode; |
859 | int err; | 743 | struct xattr_handler *handler; |
860 | 744 | ||
861 | if (!xah || !reiserfs_xattrs(dentry->d_sb) || | 745 | handler = find_xattr_handler_prefix(inode->i_sb->s_xattr, name); |
862 | get_inode_sd_version(dentry->d_inode) == STAT_DATA_V1) | 746 | |
747 | if (!handler || get_inode_sd_version(inode) == STAT_DATA_V1) | ||
863 | return -EOPNOTSUPP; | 748 | return -EOPNOTSUPP; |
864 | 749 | ||
865 | reiserfs_read_lock_xattr_i(dentry->d_inode); | 750 | return handler->get(inode, name, buffer, size); |
866 | reiserfs_read_lock_xattrs(dentry->d_sb); | ||
867 | err = xah->get(dentry->d_inode, name, buffer, size); | ||
868 | reiserfs_read_unlock_xattrs(dentry->d_sb); | ||
869 | reiserfs_read_unlock_xattr_i(dentry->d_inode); | ||
870 | return err; | ||
871 | } | 751 | } |
872 | 752 | ||
873 | /* | 753 | /* |
@@ -879,27 +759,15 @@ int | |||
879 | reiserfs_setxattr(struct dentry *dentry, const char *name, const void *value, | 759 | reiserfs_setxattr(struct dentry *dentry, const char *name, const void *value, |
880 | size_t size, int flags) | 760 | size_t size, int flags) |
881 | { | 761 | { |
882 | struct reiserfs_xattr_handler *xah = find_xattr_handler_prefix(name); | 762 | struct inode *inode = dentry->d_inode; |
883 | int err; | 763 | struct xattr_handler *handler; |
884 | int lock; | ||
885 | 764 | ||
886 | if (!xah || !reiserfs_xattrs(dentry->d_sb) || | 765 | handler = find_xattr_handler_prefix(inode->i_sb->s_xattr, name); |
887 | get_inode_sd_version(dentry->d_inode) == STAT_DATA_V1) | 766 | |
767 | if (!handler || get_inode_sd_version(inode) == STAT_DATA_V1) | ||
888 | return -EOPNOTSUPP; | 768 | return -EOPNOTSUPP; |
889 | 769 | ||
890 | reiserfs_write_lock_xattr_i(dentry->d_inode); | 770 | return handler->set(inode, name, value, size, flags); |
891 | lock = !has_xattr_dir(dentry->d_inode); | ||
892 | if (lock) | ||
893 | reiserfs_write_lock_xattrs(dentry->d_sb); | ||
894 | else | ||
895 | reiserfs_read_lock_xattrs(dentry->d_sb); | ||
896 | err = xah->set(dentry->d_inode, name, value, size, flags); | ||
897 | if (lock) | ||
898 | reiserfs_write_unlock_xattrs(dentry->d_sb); | ||
899 | else | ||
900 | reiserfs_read_unlock_xattrs(dentry->d_sb); | ||
901 | reiserfs_write_unlock_xattr_i(dentry->d_inode); | ||
902 | return err; | ||
903 | } | 771 | } |
904 | 772 | ||
905 | /* | 773 | /* |
@@ -909,86 +777,66 @@ reiserfs_setxattr(struct dentry *dentry, const char *name, const void *value, | |||
909 | */ | 777 | */ |
910 | int reiserfs_removexattr(struct dentry *dentry, const char *name) | 778 | int reiserfs_removexattr(struct dentry *dentry, const char *name) |
911 | { | 779 | { |
912 | int err; | 780 | struct inode *inode = dentry->d_inode; |
913 | struct reiserfs_xattr_handler *xah = find_xattr_handler_prefix(name); | 781 | struct xattr_handler *handler; |
782 | handler = find_xattr_handler_prefix(inode->i_sb->s_xattr, name); | ||
914 | 783 | ||
915 | if (!xah || !reiserfs_xattrs(dentry->d_sb) || | 784 | if (!handler || get_inode_sd_version(inode) == STAT_DATA_V1) |
916 | get_inode_sd_version(dentry->d_inode) == STAT_DATA_V1) | ||
917 | return -EOPNOTSUPP; | 785 | return -EOPNOTSUPP; |
918 | 786 | ||
919 | reiserfs_write_lock_xattr_i(dentry->d_inode); | 787 | return handler->set(inode, name, NULL, 0, XATTR_REPLACE); |
920 | reiserfs_read_lock_xattrs(dentry->d_sb); | ||
921 | |||
922 | /* Deletion pre-operation */ | ||
923 | if (xah->del) { | ||
924 | err = xah->del(dentry->d_inode, name); | ||
925 | if (err) | ||
926 | goto out; | ||
927 | } | ||
928 | |||
929 | err = reiserfs_xattr_del(dentry->d_inode, name); | ||
930 | |||
931 | dentry->d_inode->i_ctime = CURRENT_TIME_SEC; | ||
932 | mark_inode_dirty(dentry->d_inode); | ||
933 | |||
934 | out: | ||
935 | reiserfs_read_unlock_xattrs(dentry->d_sb); | ||
936 | reiserfs_write_unlock_xattr_i(dentry->d_inode); | ||
937 | return err; | ||
938 | } | 788 | } |
939 | 789 | ||
940 | /* This is what filldir will use: | 790 | struct listxattr_buf { |
941 | * r_pos will always contain the amount of space required for the entire | 791 | size_t size; |
942 | * list. If r_pos becomes larger than r_size, we need more space and we | 792 | size_t pos; |
943 | * return an error indicating this. If r_pos is less than r_size, then we've | 793 | char *buf; |
944 | * filled the buffer successfully and we return success */ | 794 | struct inode *inode; |
945 | struct reiserfs_listxattr_buf { | ||
946 | int r_pos; | ||
947 | int r_size; | ||
948 | char *r_buf; | ||
949 | struct inode *r_inode; | ||
950 | }; | 795 | }; |
951 | 796 | ||
952 | static int | 797 | static int listxattr_filler(void *buf, const char *name, int namelen, |
953 | reiserfs_listxattr_filler(void *buf, const char *name, int namelen, | 798 | loff_t offset, u64 ino, unsigned int d_type) |
954 | loff_t offset, u64 ino, unsigned int d_type) | ||
955 | { | 799 | { |
956 | struct reiserfs_listxattr_buf *b = (struct reiserfs_listxattr_buf *)buf; | 800 | struct listxattr_buf *b = (struct listxattr_buf *)buf; |
957 | int len = 0; | 801 | size_t size; |
958 | if (name[0] != '.' | 802 | if (name[0] != '.' || |
959 | || (namelen != 1 && (name[1] != '.' || namelen != 2))) { | 803 | (namelen != 1 && (name[1] != '.' || namelen != 2))) { |
960 | struct reiserfs_xattr_handler *xah = | 804 | struct xattr_handler *handler; |
961 | find_xattr_handler_prefix(name); | 805 | handler = find_xattr_handler_prefix(b->inode->i_sb->s_xattr, |
962 | if (!xah) | 806 | name); |
963 | return 0; /* Unsupported xattr name, skip it */ | 807 | if (!handler) /* Unsupported xattr name */ |
964 | 808 | return 0; | |
965 | /* We call ->list() twice because the operation isn't required to just | 809 | if (b->buf) { |
966 | * return the name back - we want to make sure we have enough space */ | 810 | size = handler->list(b->inode, b->buf + b->pos, |
967 | len += xah->list(b->r_inode, name, namelen, NULL); | 811 | b->size, name, namelen); |
968 | 812 | if (size > b->size) | |
969 | if (len) { | 813 | return -ERANGE; |
970 | if (b->r_pos + len + 1 <= b->r_size) { | 814 | } else { |
971 | char *p = b->r_buf + b->r_pos; | 815 | size = handler->list(b->inode, NULL, 0, name, namelen); |
972 | p += xah->list(b->r_inode, name, namelen, p); | ||
973 | *p++ = '\0'; | ||
974 | } | ||
975 | b->r_pos += len + 1; | ||
976 | } | 816 | } |
977 | } | ||
978 | 817 | ||
818 | b->pos += size; | ||
819 | } | ||
979 | return 0; | 820 | return 0; |
980 | } | 821 | } |
981 | 822 | ||
982 | /* | 823 | /* |
983 | * Inode operation listxattr() | 824 | * Inode operation listxattr() |
984 | * | 825 | * |
985 | * Preliminary locking: we down dentry->d_inode->i_mutex | 826 | * We totally ignore the generic listxattr here because it would be stupid |
827 | * not to. Since the xattrs are organized in a directory, we can just | ||
828 | * readdir to find them. | ||
986 | */ | 829 | */ |
987 | ssize_t reiserfs_listxattr(struct dentry * dentry, char *buffer, size_t size) | 830 | ssize_t reiserfs_listxattr(struct dentry * dentry, char *buffer, size_t size) |
988 | { | 831 | { |
989 | struct dentry *dir; | 832 | struct dentry *dir; |
990 | int err = 0; | 833 | int err = 0; |
991 | struct reiserfs_listxattr_buf buf; | 834 | loff_t pos = 0; |
835 | struct listxattr_buf buf = { | ||
836 | .inode = dentry->d_inode, | ||
837 | .buf = buffer, | ||
838 | .size = buffer ? size : 0, | ||
839 | }; | ||
992 | 840 | ||
993 | if (!dentry->d_inode) | 841 | if (!dentry->d_inode) |
994 | return -EINVAL; | 842 | return -EINVAL; |
@@ -997,130 +845,104 @@ ssize_t reiserfs_listxattr(struct dentry * dentry, char *buffer, size_t size) | |||
997 | get_inode_sd_version(dentry->d_inode) == STAT_DATA_V1) | 845 | get_inode_sd_version(dentry->d_inode) == STAT_DATA_V1) |
998 | return -EOPNOTSUPP; | 846 | return -EOPNOTSUPP; |
999 | 847 | ||
1000 | reiserfs_read_lock_xattr_i(dentry->d_inode); | 848 | dir = open_xa_dir(dentry->d_inode, XATTR_REPLACE); |
1001 | reiserfs_read_lock_xattrs(dentry->d_sb); | ||
1002 | dir = open_xa_dir(dentry->d_inode, FL_READONLY); | ||
1003 | reiserfs_read_unlock_xattrs(dentry->d_sb); | ||
1004 | if (IS_ERR(dir)) { | 849 | if (IS_ERR(dir)) { |
1005 | err = PTR_ERR(dir); | 850 | err = PTR_ERR(dir); |
1006 | if (err == -ENODATA) | 851 | if (err == -ENODATA) |
1007 | err = 0; /* Not an error if there aren't any xattrs */ | 852 | err = 0; /* Not an error if there aren't any xattrs */ |
1008 | goto out; | 853 | goto out; |
1009 | } | 854 | } |
1010 | 855 | ||
1011 | buf.r_buf = buffer; | 856 | mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_XATTR); |
1012 | buf.r_size = buffer ? size : 0; | 857 | err = reiserfs_readdir_dentry(dir, &buf, listxattr_filler, &pos); |
1013 | buf.r_pos = 0; | 858 | mutex_unlock(&dir->d_inode->i_mutex); |
1014 | buf.r_inode = dentry->d_inode; | ||
1015 | 859 | ||
1016 | REISERFS_I(dentry->d_inode)->i_flags |= i_has_xattr_dir; | 860 | if (!err) |
1017 | 861 | err = buf.pos; | |
1018 | err = xattr_readdir(dir->d_inode, reiserfs_listxattr_filler, &buf); | ||
1019 | if (err) | ||
1020 | goto out_dir; | ||
1021 | |||
1022 | if (buf.r_pos > buf.r_size && buffer != NULL) | ||
1023 | err = -ERANGE; | ||
1024 | else | ||
1025 | err = buf.r_pos; | ||
1026 | 862 | ||
1027 | out_dir: | ||
1028 | dput(dir); | 863 | dput(dir); |
1029 | 864 | out: | |
1030 | out: | ||
1031 | reiserfs_read_unlock_xattr_i(dentry->d_inode); | ||
1032 | return err; | 865 | return err; |
1033 | } | 866 | } |
1034 | 867 | ||
1035 | /* This is the implementation for the xattr plugin infrastructure */ | 868 | static int reiserfs_check_acl(struct inode *inode, int mask) |
1036 | static LIST_HEAD(xattr_handlers); | ||
1037 | static DEFINE_RWLOCK(handler_lock); | ||
1038 | |||
1039 | static struct reiserfs_xattr_handler *find_xattr_handler_prefix(const char | ||
1040 | *prefix) | ||
1041 | { | 869 | { |
1042 | struct reiserfs_xattr_handler *xah = NULL; | 870 | struct posix_acl *acl; |
1043 | struct list_head *p; | 871 | int error = -EAGAIN; /* do regular unix permission checks by default */ |
1044 | 872 | ||
1045 | read_lock(&handler_lock); | 873 | acl = reiserfs_get_acl(inode, ACL_TYPE_ACCESS); |
1046 | list_for_each(p, &xattr_handlers) { | 874 | |
1047 | xah = list_entry(p, struct reiserfs_xattr_handler, handlers); | 875 | if (acl) { |
1048 | if (strncmp(xah->prefix, prefix, strlen(xah->prefix)) == 0) | 876 | if (!IS_ERR(acl)) { |
1049 | break; | 877 | error = posix_acl_permission(inode, acl, mask); |
1050 | xah = NULL; | 878 | posix_acl_release(acl); |
879 | } else if (PTR_ERR(acl) != -ENODATA) | ||
880 | error = PTR_ERR(acl); | ||
1051 | } | 881 | } |
1052 | 882 | ||
1053 | read_unlock(&handler_lock); | 883 | return error; |
1054 | return xah; | ||
1055 | } | 884 | } |
1056 | 885 | ||
1057 | static void __unregister_handlers(void) | 886 | int reiserfs_permission(struct inode *inode, int mask) |
1058 | { | 887 | { |
1059 | struct reiserfs_xattr_handler *xah; | 888 | /* |
1060 | struct list_head *p, *tmp; | 889 | * We don't do permission checks on the internal objects. |
1061 | 890 | * Permissions are determined by the "owning" object. | |
1062 | list_for_each_safe(p, tmp, &xattr_handlers) { | 891 | */ |
1063 | xah = list_entry(p, struct reiserfs_xattr_handler, handlers); | 892 | if (IS_PRIVATE(inode)) |
1064 | if (xah->exit) | 893 | return 0; |
1065 | xah->exit(); | 894 | /* |
1066 | 895 | * Stat data v1 doesn't support ACLs. | |
1067 | list_del_init(p); | 896 | */ |
1068 | } | 897 | if (get_inode_sd_version(inode) == STAT_DATA_V1) |
1069 | INIT_LIST_HEAD(&xattr_handlers); | 898 | return generic_permission(inode, mask, NULL); |
899 | else | ||
900 | return generic_permission(inode, mask, reiserfs_check_acl); | ||
1070 | } | 901 | } |
1071 | 902 | ||
1072 | int __init reiserfs_xattr_register_handlers(void) | 903 | static int create_privroot(struct dentry *dentry) |
1073 | { | 904 | { |
1074 | int err = 0; | 905 | int err; |
1075 | struct reiserfs_xattr_handler *xah; | 906 | struct inode *inode = dentry->d_parent->d_inode; |
1076 | struct list_head *p; | 907 | mutex_lock_nested(&inode->i_mutex, I_MUTEX_XATTR); |
1077 | 908 | err = xattr_mkdir(inode, dentry, 0700); | |
1078 | write_lock(&handler_lock); | 909 | mutex_unlock(&inode->i_mutex); |
1079 | 910 | if (err) { | |
1080 | /* If we're already initialized, nothing to do */ | 911 | dput(dentry); |
1081 | if (!list_empty(&xattr_handlers)) { | 912 | dentry = NULL; |
1082 | write_unlock(&handler_lock); | ||
1083 | return 0; | ||
1084 | } | ||
1085 | |||
1086 | /* Add the handlers */ | ||
1087 | list_add_tail(&user_handler.handlers, &xattr_handlers); | ||
1088 | list_add_tail(&trusted_handler.handlers, &xattr_handlers); | ||
1089 | #ifdef CONFIG_REISERFS_FS_SECURITY | ||
1090 | list_add_tail(&security_handler.handlers, &xattr_handlers); | ||
1091 | #endif | ||
1092 | #ifdef CONFIG_REISERFS_FS_POSIX_ACL | ||
1093 | list_add_tail(&posix_acl_access_handler.handlers, &xattr_handlers); | ||
1094 | list_add_tail(&posix_acl_default_handler.handlers, &xattr_handlers); | ||
1095 | #endif | ||
1096 | |||
1097 | /* Run initializers, if available */ | ||
1098 | list_for_each(p, &xattr_handlers) { | ||
1099 | xah = list_entry(p, struct reiserfs_xattr_handler, handlers); | ||
1100 | if (xah->init) { | ||
1101 | err = xah->init(); | ||
1102 | if (err) { | ||
1103 | list_del_init(p); | ||
1104 | break; | ||
1105 | } | ||
1106 | } | ||
1107 | } | 913 | } |
1108 | 914 | ||
1109 | /* Clean up other handlers, if any failed */ | 915 | if (dentry && dentry->d_inode) |
1110 | if (err) | 916 | reiserfs_info(dentry->d_sb, "Created %s - reserved for xattr " |
1111 | __unregister_handlers(); | 917 | "storage.\n", PRIVROOT_NAME); |
1112 | 918 | ||
1113 | write_unlock(&handler_lock); | ||
1114 | return err; | 919 | return err; |
1115 | } | 920 | } |
1116 | 921 | ||
1117 | void reiserfs_xattr_unregister_handlers(void) | 922 | static int xattr_mount_check(struct super_block *s) |
1118 | { | 923 | { |
1119 | write_lock(&handler_lock); | 924 | /* We need generation numbers to ensure that the oid mapping is correct |
1120 | __unregister_handlers(); | 925 | * v3.5 filesystems don't have them. */ |
1121 | write_unlock(&handler_lock); | 926 | if (old_format_only(s)) { |
927 | if (reiserfs_xattrs_optional(s)) { | ||
928 | /* Old format filesystem, but optional xattrs have | ||
929 | * been enabled. Error out. */ | ||
930 | reiserfs_warning(s, "jdm-2005", | ||
931 | "xattrs/ACLs not supported " | ||
932 | "on pre-v3.6 format filesystems. " | ||
933 | "Failing mount."); | ||
934 | return -EOPNOTSUPP; | ||
935 | } | ||
936 | } | ||
937 | |||
938 | return 0; | ||
1122 | } | 939 | } |
1123 | 940 | ||
941 | #else | ||
942 | int __init reiserfs_xattr_register_handlers(void) { return 0; } | ||
943 | void reiserfs_xattr_unregister_handlers(void) {} | ||
944 | #endif | ||
945 | |||
1124 | /* This will catch lookups from the fs root to .reiserfs_priv */ | 946 | /* This will catch lookups from the fs root to .reiserfs_priv */ |
1125 | static int | 947 | static int |
1126 | xattr_lookup_poison(struct dentry *dentry, struct qstr *q1, struct qstr *name) | 948 | xattr_lookup_poison(struct dentry *dentry, struct qstr *q1, struct qstr *name) |
@@ -1147,48 +969,23 @@ int reiserfs_xattr_init(struct super_block *s, int mount_flags) | |||
1147 | { | 969 | { |
1148 | int err = 0; | 970 | int err = 0; |
1149 | 971 | ||
1150 | /* We need generation numbers to ensure that the oid mapping is correct | 972 | #ifdef CONFIG_REISERFS_FS_XATTR |
1151 | * v3.5 filesystems don't have them. */ | 973 | err = xattr_mount_check(s); |
1152 | if (!old_format_only(s)) { | 974 | if (err) |
1153 | set_bit(REISERFS_XATTRS, &(REISERFS_SB(s)->s_mount_opt)); | ||
1154 | } else if (reiserfs_xattrs_optional(s)) { | ||
1155 | /* Old format filesystem, but optional xattrs have been enabled | ||
1156 | * at mount time. Error out. */ | ||
1157 | reiserfs_warning(s, "xattrs/ACLs not supported on pre v3.6 " | ||
1158 | "format filesystem. Failing mount."); | ||
1159 | err = -EOPNOTSUPP; | ||
1160 | goto error; | 975 | goto error; |
1161 | } else { | 976 | #endif |
1162 | /* Old format filesystem, but no optional xattrs have been enabled. This | ||
1163 | * means we silently disable xattrs on the filesystem. */ | ||
1164 | clear_bit(REISERFS_XATTRS, &(REISERFS_SB(s)->s_mount_opt)); | ||
1165 | } | ||
1166 | 977 | ||
1167 | /* If we don't have the privroot located yet - go find it */ | 978 | /* If we don't have the privroot located yet - go find it */ |
1168 | if (reiserfs_xattrs(s) && !REISERFS_SB(s)->priv_root) { | 979 | if (!REISERFS_SB(s)->priv_root) { |
1169 | struct dentry *dentry; | 980 | struct dentry *dentry; |
1170 | dentry = lookup_one_len(PRIVROOT_NAME, s->s_root, | 981 | dentry = lookup_one_len(PRIVROOT_NAME, s->s_root, |
1171 | strlen(PRIVROOT_NAME)); | 982 | strlen(PRIVROOT_NAME)); |
1172 | if (!IS_ERR(dentry)) { | 983 | if (!IS_ERR(dentry)) { |
1173 | if (!(mount_flags & MS_RDONLY) && !dentry->d_inode) { | 984 | #ifdef CONFIG_REISERFS_FS_XATTR |
1174 | struct inode *inode = dentry->d_parent->d_inode; | 985 | if (!(mount_flags & MS_RDONLY) && !dentry->d_inode) |
1175 | mutex_lock_nested(&inode->i_mutex, | 986 | err = create_privroot(dentry); |
1176 | I_MUTEX_XATTR); | 987 | #endif |
1177 | err = inode->i_op->mkdir(inode, dentry, 0700); | 988 | if (!dentry->d_inode) { |
1178 | mutex_unlock(&inode->i_mutex); | ||
1179 | if (err) { | ||
1180 | dput(dentry); | ||
1181 | dentry = NULL; | ||
1182 | } | ||
1183 | |||
1184 | if (dentry && dentry->d_inode) | ||
1185 | reiserfs_warning(s, | ||
1186 | "Created %s on %s - reserved for " | ||
1187 | "xattr storage.", | ||
1188 | PRIVROOT_NAME, | ||
1189 | reiserfs_bdevname | ||
1190 | (inode->i_sb)); | ||
1191 | } else if (!dentry->d_inode) { | ||
1192 | dput(dentry); | 989 | dput(dentry); |
1193 | dentry = NULL; | 990 | dentry = NULL; |
1194 | } | 991 | } |
@@ -1197,73 +994,41 @@ int reiserfs_xattr_init(struct super_block *s, int mount_flags) | |||
1197 | 994 | ||
1198 | if (!err && dentry) { | 995 | if (!err && dentry) { |
1199 | s->s_root->d_op = &xattr_lookup_poison_ops; | 996 | s->s_root->d_op = &xattr_lookup_poison_ops; |
1200 | reiserfs_mark_inode_private(dentry->d_inode); | 997 | dentry->d_inode->i_flags |= S_PRIVATE; |
1201 | REISERFS_SB(s)->priv_root = dentry; | 998 | REISERFS_SB(s)->priv_root = dentry; |
1202 | } else if (!(mount_flags & MS_RDONLY)) { /* xattrs are unavailable */ | 999 | #ifdef CONFIG_REISERFS_FS_XATTR |
1203 | /* If we're read-only it just means that the dir hasn't been | 1000 | /* xattrs are unavailable */ |
1204 | * created. Not an error -- just no xattrs on the fs. We'll | 1001 | } else if (!(mount_flags & MS_RDONLY)) { |
1205 | * check again if we go read-write */ | 1002 | /* If we're read-only it just means that the dir |
1206 | reiserfs_warning(s, "xattrs/ACLs enabled and couldn't " | 1003 | * hasn't been created. Not an error -- just no |
1207 | "find/create .reiserfs_priv. Failing mount."); | 1004 | * xattrs on the fs. We'll check again if we |
1005 | * go read-write */ | ||
1006 | reiserfs_warning(s, "jdm-20006", | ||
1007 | "xattrs/ACLs enabled and couldn't " | ||
1008 | "find/create .reiserfs_priv. " | ||
1009 | "Failing mount."); | ||
1208 | err = -EOPNOTSUPP; | 1010 | err = -EOPNOTSUPP; |
1011 | #endif | ||
1209 | } | 1012 | } |
1210 | } | 1013 | } |
1211 | 1014 | ||
1212 | error: | 1015 | #ifdef CONFIG_REISERFS_FS_XATTR |
1213 | /* This is only nonzero if there was an error initializing the xattr | 1016 | if (!err) |
1214 | * directory or if there is a condition where we don't support them. */ | 1017 | s->s_xattr = reiserfs_xattr_handlers; |
1018 | |||
1019 | error: | ||
1215 | if (err) { | 1020 | if (err) { |
1216 | clear_bit(REISERFS_XATTRS, &(REISERFS_SB(s)->s_mount_opt)); | ||
1217 | clear_bit(REISERFS_XATTRS_USER, &(REISERFS_SB(s)->s_mount_opt)); | 1021 | clear_bit(REISERFS_XATTRS_USER, &(REISERFS_SB(s)->s_mount_opt)); |
1218 | clear_bit(REISERFS_POSIXACL, &(REISERFS_SB(s)->s_mount_opt)); | 1022 | clear_bit(REISERFS_POSIXACL, &(REISERFS_SB(s)->s_mount_opt)); |
1219 | } | 1023 | } |
1024 | #endif | ||
1220 | 1025 | ||
1221 | /* The super_block MS_POSIXACL must mirror the (no)acl mount option. */ | 1026 | /* The super_block MS_POSIXACL must mirror the (no)acl mount option. */ |
1222 | s->s_flags = s->s_flags & ~MS_POSIXACL; | 1027 | s->s_flags = s->s_flags & ~MS_POSIXACL; |
1028 | #ifdef CONFIG_REISERFS_FS_POSIX_ACL | ||
1223 | if (reiserfs_posixacl(s)) | 1029 | if (reiserfs_posixacl(s)) |
1224 | s->s_flags |= MS_POSIXACL; | 1030 | s->s_flags |= MS_POSIXACL; |
1031 | #endif | ||
1225 | 1032 | ||
1226 | return err; | 1033 | return err; |
1227 | } | 1034 | } |
1228 | |||
1229 | static int reiserfs_check_acl(struct inode *inode, int mask) | ||
1230 | { | ||
1231 | struct posix_acl *acl; | ||
1232 | int error = -EAGAIN; /* do regular unix permission checks by default */ | ||
1233 | |||
1234 | reiserfs_read_lock_xattr_i(inode); | ||
1235 | reiserfs_read_lock_xattrs(inode->i_sb); | ||
1236 | |||
1237 | acl = reiserfs_get_acl(inode, ACL_TYPE_ACCESS); | ||
1238 | |||
1239 | reiserfs_read_unlock_xattrs(inode->i_sb); | ||
1240 | reiserfs_read_unlock_xattr_i(inode); | ||
1241 | |||
1242 | if (acl) { | ||
1243 | if (!IS_ERR(acl)) { | ||
1244 | error = posix_acl_permission(inode, acl, mask); | ||
1245 | posix_acl_release(acl); | ||
1246 | } else if (PTR_ERR(acl) != -ENODATA) | ||
1247 | error = PTR_ERR(acl); | ||
1248 | } | ||
1249 | |||
1250 | return error; | ||
1251 | } | ||
1252 | |||
1253 | int reiserfs_permission(struct inode *inode, int mask) | ||
1254 | { | ||
1255 | /* | ||
1256 | * We don't do permission checks on the internal objects. | ||
1257 | * Permissions are determined by the "owning" object. | ||
1258 | */ | ||
1259 | if (is_reiserfs_priv_object(inode)) | ||
1260 | return 0; | ||
1261 | |||
1262 | /* | ||
1263 | * Stat data v1 doesn't support ACLs. | ||
1264 | */ | ||
1265 | if (get_inode_sd_version(inode) == STAT_DATA_V1) | ||
1266 | return generic_permission(inode, mask, NULL); | ||
1267 | else | ||
1268 | return generic_permission(inode, mask, reiserfs_check_acl); | ||
1269 | } | ||