Blame view

fs/reiserfs/xattr_acl.c 12.2 KB
16f7e0fe2   Randy Dunlap   [PATCH] capable/c...
1
  #include <linux/capability.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
3
4
5
6
7
  #include <linux/fs.h>
  #include <linux/posix_acl.h>
  #include <linux/reiserfs_fs.h>
  #include <linux/errno.h>
  #include <linux/pagemap.h>
  #include <linux/xattr.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
8
  #include <linux/slab.h>
9a59f452a   Christoph Hellwig   [PATCH] remove <l...
9
  #include <linux/posix_acl_xattr.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
10
11
12
  #include <linux/reiserfs_xattr.h>
  #include <linux/reiserfs_acl.h>
  #include <asm/uaccess.h>
0ab2621eb   Jeff Mahoney   reiserfs: journal...
13
14
  static int reiserfs_set_acl(struct reiserfs_transaction_handle *th,
  			    struct inode *inode, int type,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
15
  			    struct posix_acl *acl);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
16
17
  
  static int
431547b3c   Christoph Hellwig   sanitize xattr ha...
18
19
  posix_acl_set(struct dentry *dentry, const char *name, const void *value,
  		size_t size, int flags, int type)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
20
  {
431547b3c   Christoph Hellwig   sanitize xattr ha...
21
  	struct inode *inode = dentry->d_inode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
22
  	struct posix_acl *acl;
0ab2621eb   Jeff Mahoney   reiserfs: journal...
23
24
25
  	int error, error2;
  	struct reiserfs_transaction_handle th;
  	size_t jcreate_blocks;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
26
27
  	if (!reiserfs_posixacl(inode->i_sb))
  		return -EOPNOTSUPP;
2e1496707   Serge E. Hallyn   userns: rename is...
28
  	if (!inode_owner_or_capable(inode))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
29
30
31
32
33
34
35
36
37
38
39
40
41
  		return -EPERM;
  
  	if (value) {
  		acl = posix_acl_from_xattr(value, size);
  		if (IS_ERR(acl)) {
  			return PTR_ERR(acl);
  		} else if (acl) {
  			error = posix_acl_valid(acl);
  			if (error)
  				goto release_and_out;
  		}
  	} else
  		acl = NULL;
0ab2621eb   Jeff Mahoney   reiserfs: journal...
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
  	/* Pessimism: We can't assume that anything from the xattr root up
  	 * has been created. */
  
  	jcreate_blocks = reiserfs_xattr_jcreate_nblocks(inode) +
  			 reiserfs_xattr_nblocks(inode, size) * 2;
  
  	reiserfs_write_lock(inode->i_sb);
  	error = journal_begin(&th, inode->i_sb, jcreate_blocks);
  	if (error == 0) {
  		error = reiserfs_set_acl(&th, inode, type, acl);
  		error2 = journal_end(&th, inode->i_sb, jcreate_blocks);
  		if (error2)
  			error = error2;
  	}
  	reiserfs_write_unlock(inode->i_sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
57

bd4c625c0   Linus Torvalds   reiserfs: run scr...
58
        release_and_out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
59
60
61
  	posix_acl_release(acl);
  	return error;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
62
  static int
431547b3c   Christoph Hellwig   sanitize xattr ha...
63
64
  posix_acl_get(struct dentry *dentry, const char *name, void *buffer,
  		size_t size, int type)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
65
66
67
  {
  	struct posix_acl *acl;
  	int error;
431547b3c   Christoph Hellwig   sanitize xattr ha...
68
  	if (!reiserfs_posixacl(dentry->d_sb))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
69
  		return -EOPNOTSUPP;
431547b3c   Christoph Hellwig   sanitize xattr ha...
70
  	acl = reiserfs_get_acl(dentry->d_inode, type);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
71
72
73
74
75
76
77
78
79
  	if (IS_ERR(acl))
  		return PTR_ERR(acl);
  	if (acl == NULL)
  		return -ENODATA;
  	error = posix_acl_to_xattr(acl, buffer, size);
  	posix_acl_release(acl);
  
  	return error;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
80
81
82
  /*
   * Convert from filesystem to in-memory representation.
   */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
83
  static struct posix_acl *posix_acl_from_disk(const void *value, size_t size)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
84
85
86
87
88
89
90
91
  {
  	const char *end = (char *)value + size;
  	int n, count;
  	struct posix_acl *acl;
  
  	if (!value)
  		return NULL;
  	if (size < sizeof(reiserfs_acl_header))
bd4c625c0   Linus Torvalds   reiserfs: run scr...
92
93
  		return ERR_PTR(-EINVAL);
  	if (((reiserfs_acl_header *) value)->a_version !=
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
94
95
96
97
98
99
100
101
102
103
104
  	    cpu_to_le32(REISERFS_ACL_VERSION))
  		return ERR_PTR(-EINVAL);
  	value = (char *)value + sizeof(reiserfs_acl_header);
  	count = reiserfs_acl_count(size);
  	if (count < 0)
  		return ERR_PTR(-EINVAL);
  	if (count == 0)
  		return NULL;
  	acl = posix_acl_alloc(count, GFP_NOFS);
  	if (!acl)
  		return ERR_PTR(-ENOMEM);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
105
106
  	for (n = 0; n < count; n++) {
  		reiserfs_acl_entry *entry = (reiserfs_acl_entry *) value;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
107
108
  		if ((char *)value + sizeof(reiserfs_acl_entry_short) > end)
  			goto fail;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
109
  		acl->a_entries[n].e_tag = le16_to_cpu(entry->e_tag);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
110
  		acl->a_entries[n].e_perm = le16_to_cpu(entry->e_perm);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
111
112
113
114
115
116
117
118
119
120
121
122
123
124
  		switch (acl->a_entries[n].e_tag) {
  		case ACL_USER_OBJ:
  		case ACL_GROUP_OBJ:
  		case ACL_MASK:
  		case ACL_OTHER:
  			value = (char *)value +
  			    sizeof(reiserfs_acl_entry_short);
  			acl->a_entries[n].e_id = ACL_UNDEFINED_ID;
  			break;
  
  		case ACL_USER:
  		case ACL_GROUP:
  			value = (char *)value + sizeof(reiserfs_acl_entry);
  			if ((char *)value > end)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
125
  				goto fail;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
126
127
128
129
130
  			acl->a_entries[n].e_id = le32_to_cpu(entry->e_id);
  			break;
  
  		default:
  			goto fail;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
131
132
133
134
135
  		}
  	}
  	if (value != end)
  		goto fail;
  	return acl;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
136
        fail:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
137
138
139
140
141
142
143
  	posix_acl_release(acl);
  	return ERR_PTR(-EINVAL);
  }
  
  /*
   * Convert from in-memory to filesystem representation.
   */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
144
  static void *posix_acl_to_disk(const struct posix_acl *acl, size_t * size)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
145
146
147
148
149
150
  {
  	reiserfs_acl_header *ext_acl;
  	char *e;
  	int n;
  
  	*size = reiserfs_acl_size(acl->a_count);
5cbded585   Robert P. J. Day   [PATCH] getting r...
151
  	ext_acl = kmalloc(sizeof(reiserfs_acl_header) +
bd4c625c0   Linus Torvalds   reiserfs: run scr...
152
153
154
  						  acl->a_count *
  						  sizeof(reiserfs_acl_entry),
  						  GFP_NOFS);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
155
156
157
158
  	if (!ext_acl)
  		return ERR_PTR(-ENOMEM);
  	ext_acl->a_version = cpu_to_le32(REISERFS_ACL_VERSION);
  	e = (char *)ext_acl + sizeof(reiserfs_acl_header);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
159
160
161
  	for (n = 0; n < acl->a_count; n++) {
  		reiserfs_acl_entry *entry = (reiserfs_acl_entry *) e;
  		entry->e_tag = cpu_to_le16(acl->a_entries[n].e_tag);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
162
  		entry->e_perm = cpu_to_le16(acl->a_entries[n].e_perm);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
  		switch (acl->a_entries[n].e_tag) {
  		case ACL_USER:
  		case ACL_GROUP:
  			entry->e_id = cpu_to_le32(acl->a_entries[n].e_id);
  			e += sizeof(reiserfs_acl_entry);
  			break;
  
  		case ACL_USER_OBJ:
  		case ACL_GROUP_OBJ:
  		case ACL_MASK:
  		case ACL_OTHER:
  			e += sizeof(reiserfs_acl_entry_short);
  			break;
  
  		default:
  			goto fail;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
179
180
181
  		}
  	}
  	return (char *)ext_acl;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
182
        fail:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
183
184
185
186
187
188
189
  	kfree(ext_acl);
  	return ERR_PTR(-EINVAL);
  }
  
  /*
   * Inode operation get_posix_acl().
   *
1b1dcc1b5   Jes Sorensen   [PATCH] mutex sub...
190
   * inode->i_mutex: down
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
191
192
   * BKL held [before 2.5.x]
   */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
193
  struct posix_acl *reiserfs_get_acl(struct inode *inode, int type)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
194
195
  {
  	char *name, *value;
073aaa1b1   Al Viro   helpers for acl c...
196
  	struct posix_acl *acl;
3cdc409c1   Adrian Bunk   [PATCH] reiserfs/...
197
  	int size;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
198
  	int retval;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
199

073aaa1b1   Al Viro   helpers for acl c...
200
201
202
  	acl = get_cached_acl(inode, type);
  	if (acl != ACL_NOT_CACHED)
  		return acl;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
203
204
205
  	switch (type) {
  	case ACL_TYPE_ACCESS:
  		name = POSIX_ACL_XATTR_ACCESS;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
206
207
208
  		break;
  	case ACL_TYPE_DEFAULT:
  		name = POSIX_ACL_XATTR_DEFAULT;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
209
210
  		break;
  	default:
073aaa1b1   Al Viro   helpers for acl c...
211
  		BUG();
bd4c625c0   Linus Torvalds   reiserfs: run scr...
212
  	}
bd4c625c0   Linus Torvalds   reiserfs: run scr...
213
  	size = reiserfs_xattr_get(inode, name, NULL, 0);
3cdc409c1   Adrian Bunk   [PATCH] reiserfs/...
214
  	if (size < 0) {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
215
  		if (size == -ENODATA || size == -ENOSYS) {
073aaa1b1   Al Viro   helpers for acl c...
216
  			set_cached_acl(inode, type, NULL);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
217
218
219
220
  			return NULL;
  		}
  		return ERR_PTR(size);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
221

bd4c625c0   Linus Torvalds   reiserfs: run scr...
222
223
224
  	value = kmalloc(size, GFP_NOFS);
  	if (!value)
  		return ERR_PTR(-ENOMEM);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
225
226
227
228
229
230
  
  	retval = reiserfs_xattr_get(inode, name, value, size);
  	if (retval == -ENODATA || retval == -ENOSYS) {
  		/* This shouldn't actually happen as it should have
  		   been caught above.. but just in case */
  		acl = NULL;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
231
  	} else if (retval < 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
232
233
234
  		acl = ERR_PTR(retval);
  	} else {
  		acl = posix_acl_from_disk(value, retval);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
235
  	}
073aaa1b1   Al Viro   helpers for acl c...
236
237
  	if (!IS_ERR(acl))
  		set_cached_acl(inode, type, acl);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
238
239
240
241
242
243
244
245
  
  	kfree(value);
  	return acl;
  }
  
  /*
   * Inode operation set_posix_acl().
   *
1b1dcc1b5   Jes Sorensen   [PATCH] mutex sub...
246
   * inode->i_mutex: down
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
247
248
249
   * BKL held [before 2.5.x]
   */
  static int
0ab2621eb   Jeff Mahoney   reiserfs: journal...
250
251
  reiserfs_set_acl(struct reiserfs_transaction_handle *th, struct inode *inode,
  		 int type, struct posix_acl *acl)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
252
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
253
  	char *name;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
254
  	void *value = NULL;
48b32a355   Jeff Mahoney   reiserfs: use gen...
255
  	size_t size = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
256
  	int error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
257
258
259
  
  	if (S_ISLNK(inode->i_mode))
  		return -EOPNOTSUPP;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
260
261
262
  	switch (type) {
  	case ACL_TYPE_ACCESS:
  		name = POSIX_ACL_XATTR_ACCESS;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
263
  		if (acl) {
d6952123b   Al Viro   switch posix_acl_...
264
  			error = posix_acl_equiv_mode(acl, &inode->i_mode);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
265
266
267
  			if (error < 0)
  				return error;
  			else {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
268
269
270
271
272
273
274
  				if (error == 0)
  					acl = NULL;
  			}
  		}
  		break;
  	case ACL_TYPE_DEFAULT:
  		name = POSIX_ACL_XATTR_DEFAULT;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
275
276
277
278
279
280
281
282
283
284
285
  		if (!S_ISDIR(inode->i_mode))
  			return acl ? -EACCES : 0;
  		break;
  	default:
  		return -EINVAL;
  	}
  
  	if (acl) {
  		value = posix_acl_to_disk(acl, &size);
  		if (IS_ERR(value))
  			return (int)PTR_ERR(value);
48b32a355   Jeff Mahoney   reiserfs: use gen...
286
  	}
0ab2621eb   Jeff Mahoney   reiserfs: journal...
287
  	error = reiserfs_xattr_set_handle(th, inode, name, value, size, 0);
48b32a355   Jeff Mahoney   reiserfs: use gen...
288
289
290
291
292
293
294
295
296
297
298
  
  	/*
  	 * Ensure that the inode gets dirtied if we're only using
  	 * the mode bits and an old ACL didn't exist. We don't need
  	 * to check if the inode is hashed here since we won't get
  	 * called by reiserfs_inherit_default_acl().
  	 */
  	if (error == -ENODATA) {
  		error = 0;
  		if (type == ACL_TYPE_ACCESS) {
  			inode->i_ctime = CURRENT_TIME_SEC;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
299
  			mark_inode_dirty(inode);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
300
301
  		}
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
302

833d304b2   James Lamanna   [PATCH] reiserfs:...
303
  	kfree(value);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
304

d984561b3   Jeff Mahoney   reiserfs: elimina...
305
  	if (!error)
073aaa1b1   Al Viro   helpers for acl c...
306
  		set_cached_acl(inode, type, acl);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
307
308
309
  
  	return error;
  }
1b1dcc1b5   Jes Sorensen   [PATCH] mutex sub...
310
  /* dir->i_mutex: locked,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
311
312
   * inode is new and not released into the wild yet */
  int
0ab2621eb   Jeff Mahoney   reiserfs: journal...
313
314
  reiserfs_inherit_default_acl(struct reiserfs_transaction_handle *th,
  			     struct inode *dir, struct dentry *dentry,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
315
  			     struct inode *inode)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
316
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
  	struct posix_acl *acl;
  	int err = 0;
  
  	/* ACLs only get applied to files and directories */
  	if (S_ISLNK(inode->i_mode))
  		return 0;
  
  	/* ACLs can only be used on "new" objects, so if it's an old object
  	 * there is nothing to inherit from */
  	if (get_inode_sd_version(dir) == STAT_DATA_V1)
  		goto apply_umask;
  
  	/* Don't apply ACLs to objects in the .reiserfs_priv tree.. This
  	 * would be useless since permissions are ignored, and a pain because
  	 * it introduces locking cycles */
6dfede696   Jeff Mahoney   reiserfs: remove ...
332
333
  	if (IS_PRIVATE(dir)) {
  		inode->i_flags |= S_PRIVATE;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
334
335
336
337
  		goto apply_umask;
  	}
  
  	acl = reiserfs_get_acl(dir, ACL_TYPE_DEFAULT);
7a77b15d9   Al Viro   switch reiserfs t...
338
  	if (IS_ERR(acl))
bd4c625c0   Linus Torvalds   reiserfs: run scr...
339
  		return PTR_ERR(acl);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
340
341
  
  	if (acl) {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
342
343
  		/* Copy the default ACL to the default ACL of a new directory */
  		if (S_ISDIR(inode->i_mode)) {
0ab2621eb   Jeff Mahoney   reiserfs: journal...
344
345
  			err = reiserfs_set_acl(th, inode, ACL_TYPE_DEFAULT,
  					       acl);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
346
347
348
349
350
351
  			if (err)
  				goto cleanup;
  		}
  
  		/* Now we reconcile the new ACL and the mode,
  		   potentially modifying both */
d3fb61207   Al Viro   switch posix_acl_...
352
  		err = posix_acl_create(&acl, GFP_NOFS, &inode->i_mode);
826cae2f2   Al Viro   kill boilerplates...
353
354
  		if (err < 0)
  			return err;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
355

826cae2f2   Al Viro   kill boilerplates...
356
357
358
  		/* If we need an ACL.. */
  		if (err > 0)
  			err = reiserfs_set_acl(th, inode, ACL_TYPE_ACCESS, acl);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
359
360
361
362
363
  	      cleanup:
  		posix_acl_release(acl);
  	} else {
  	      apply_umask:
  		/* no ACL, apply umask */
ce3b0f8d5   Al Viro   New helper - curr...
364
  		inode->i_mode &= ~current_umask();
bd4c625c0   Linus Torvalds   reiserfs: run scr...
365
366
367
  	}
  
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
368
  }
0ab2621eb   Jeff Mahoney   reiserfs: journal...
369
370
371
372
373
374
375
376
377
378
379
  /* This is used to cache the default acl before a new object is created.
   * The biggest reason for this is to get an idea of how many blocks will
   * actually be required for the create operation if we must inherit an ACL.
   * An ACL write can add up to 3 object creations and an additional file write
   * so we'd prefer not to reserve that many blocks in the journal if we can.
   * It also has the advantage of not loading the ACL with a transaction open,
   * this may seem silly, but if the owner of the directory is doing the
   * creation, the ACL may not be loaded since the permissions wouldn't require
   * it.
   * We return the number of blocks required for the transaction.
   */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
380
  int reiserfs_cache_default_acl(struct inode *inode)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
381
  {
0ab2621eb   Jeff Mahoney   reiserfs: journal...
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
  	struct posix_acl *acl;
  	int nblocks = 0;
  
  	if (IS_PRIVATE(inode))
  		return 0;
  
  	acl = reiserfs_get_acl(inode, ACL_TYPE_DEFAULT);
  
  	if (acl && !IS_ERR(acl)) {
  		int size = reiserfs_acl_size(acl->a_count);
  
  		/* Other xattrs can be created during inode creation. We don't
  		 * want to claim too many blocks, so we check to see if we
  		 * we need to create the tree to the xattrs, and then we
  		 * just want two files. */
  		nblocks = reiserfs_xattr_jcreate_nblocks(inode);
  		nblocks += JOURNAL_BLOCKS_PER_OBJECT(inode->i_sb);
  
  		REISERFS_I(inode)->i_flags |= i_has_xattr_dir;
  
  		/* We need to account for writes + bitmaps for two files */
  		nblocks += reiserfs_xattr_nblocks(inode, size) * 4;
  		posix_acl_release(acl);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
405
  	}
0ab2621eb   Jeff Mahoney   reiserfs: journal...
406
  	return nblocks;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
407
  }
bd4c625c0   Linus Torvalds   reiserfs: run scr...
408
  int reiserfs_acl_chmod(struct inode *inode)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
409
  {
bc26ab5f6   Al Viro   kill boilerplate ...
410
411
412
413
  	struct reiserfs_transaction_handle th;
  	struct posix_acl *acl;
  	size_t size;
  	int depth;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
414
  	int error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
415

bd4c625c0   Linus Torvalds   reiserfs: run scr...
416
417
  	if (S_ISLNK(inode->i_mode))
  		return -EOPNOTSUPP;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
418

bd4c625c0   Linus Torvalds   reiserfs: run scr...
419
420
421
  	if (get_inode_sd_version(inode) == STAT_DATA_V1 ||
  	    !reiserfs_posixacl(inode->i_sb)) {
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
422
  	}
6c2870541   Frederic Weisbecker   reiserfs: Don't c...
423
  	reiserfs_write_unlock(inode->i_sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
424
  	acl = reiserfs_get_acl(inode, ACL_TYPE_ACCESS);
6c2870541   Frederic Weisbecker   reiserfs: Don't c...
425
  	reiserfs_write_lock(inode->i_sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
426
427
428
429
  	if (!acl)
  		return 0;
  	if (IS_ERR(acl))
  		return PTR_ERR(acl);
bc26ab5f6   Al Viro   kill boilerplate ...
430
431
432
433
434
435
436
  	error = posix_acl_chmod(&acl, GFP_NOFS, inode->i_mode);
  	if (error)
  		return error;
  
  	size = reiserfs_xattr_nblocks(inode, reiserfs_acl_size(acl->a_count));
  	depth = reiserfs_write_lock_once(inode->i_sb);
  	error = journal_begin(&th, inode->i_sb, size * 2);
0ab2621eb   Jeff Mahoney   reiserfs: journal...
437
  	if (!error) {
bc26ab5f6   Al Viro   kill boilerplate ...
438
439
440
441
442
  		int error2;
  		error = reiserfs_set_acl(&th, inode, ACL_TYPE_ACCESS, acl);
  		error2 = journal_end(&th, inode->i_sb, size * 2);
  		if (error2)
  			error = error2;
0ab2621eb   Jeff Mahoney   reiserfs: journal...
443
  	}
bc26ab5f6   Al Viro   kill boilerplate ...
444
445
  	reiserfs_write_unlock_once(inode->i_sb, depth);
  	posix_acl_release(acl);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
446
  	return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
447
  }
431547b3c   Christoph Hellwig   sanitize xattr ha...
448
  static size_t posix_acl_access_list(struct dentry *dentry, char *list,
48b32a355   Jeff Mahoney   reiserfs: use gen...
449
  				    size_t list_size, const char *name,
431547b3c   Christoph Hellwig   sanitize xattr ha...
450
  				    size_t name_len, int type)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
451
  {
48b32a355   Jeff Mahoney   reiserfs: use gen...
452
  	const size_t size = sizeof(POSIX_ACL_XATTR_ACCESS);
431547b3c   Christoph Hellwig   sanitize xattr ha...
453
  	if (!reiserfs_posixacl(dentry->d_sb))
bd4c625c0   Linus Torvalds   reiserfs: run scr...
454
  		return 0;
48b32a355   Jeff Mahoney   reiserfs: use gen...
455
456
457
  	if (list && size <= list_size)
  		memcpy(list, POSIX_ACL_XATTR_ACCESS, size);
  	return size;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
458
  }
94d09a98c   Stephen Hemminger   reiserfs: constif...
459
  const struct xattr_handler reiserfs_posix_acl_access_handler = {
9a59f452a   Christoph Hellwig   [PATCH] remove <l...
460
  	.prefix = POSIX_ACL_XATTR_ACCESS,
431547b3c   Christoph Hellwig   sanitize xattr ha...
461
462
463
  	.flags = ACL_TYPE_ACCESS,
  	.get = posix_acl_get,
  	.set = posix_acl_set,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
464
465
  	.list = posix_acl_access_list,
  };
431547b3c   Christoph Hellwig   sanitize xattr ha...
466
  static size_t posix_acl_default_list(struct dentry *dentry, char *list,
48b32a355   Jeff Mahoney   reiserfs: use gen...
467
  				     size_t list_size, const char *name,
431547b3c   Christoph Hellwig   sanitize xattr ha...
468
  				     size_t name_len, int type)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
469
  {
48b32a355   Jeff Mahoney   reiserfs: use gen...
470
  	const size_t size = sizeof(POSIX_ACL_XATTR_DEFAULT);
431547b3c   Christoph Hellwig   sanitize xattr ha...
471
  	if (!reiserfs_posixacl(dentry->d_sb))
bd4c625c0   Linus Torvalds   reiserfs: run scr...
472
  		return 0;
48b32a355   Jeff Mahoney   reiserfs: use gen...
473
474
475
  	if (list && size <= list_size)
  		memcpy(list, POSIX_ACL_XATTR_DEFAULT, size);
  	return size;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
476
  }
94d09a98c   Stephen Hemminger   reiserfs: constif...
477
  const struct xattr_handler reiserfs_posix_acl_default_handler = {
9a59f452a   Christoph Hellwig   [PATCH] remove <l...
478
  	.prefix = POSIX_ACL_XATTR_DEFAULT,
431547b3c   Christoph Hellwig   sanitize xattr ha...
479
480
481
  	.flags = ACL_TYPE_DEFAULT,
  	.get = posix_acl_get,
  	.set = posix_acl_set,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
482
483
  	.list = posix_acl_default_list,
  };