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