Blame view

fs/ext4/xattr.c 41.9 KB
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
1
  /*
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
2
   * linux/fs/ext4/xattr.c
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
3
4
5
6
   *
   * Copyright (C) 2001-2003 Andreas Gruenbacher, <agruen@suse.de>
   *
   * Fix by Harrison Xing <harrison@mountainviewdata.com>.
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
7
   * Ext4 code with a lot of help from Eric Jarman <ejarman@acm.org>.
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
   * Extended attributes for symlinks and special files added per
   *  suggestion of Luka Renko <luka.renko@hermes.si>.
   * xattr consolidation Copyright (c) 2004 James Morris <jmorris@redhat.com>,
   *  Red Hat Inc.
   * ea-in-inode support by Alex Tomas <alex@clusterfs.com> aka bzzz
   *  and Andreas Gruenbacher <agruen@suse.de>.
   */
  
  /*
   * Extended attributes are stored directly in inodes (on file systems with
   * inodes bigger than 128 bytes) and on additional disk blocks. The i_file_acl
   * field contains the block number if an inode uses an additional block. All
   * attributes must fit in the inode and one additional block. Blocks that
   * contain the identical set of attributes may be shared among several inodes.
   * Identical blocks are detected by keeping a cache of blocks that have
   * recently been accessed.
   *
   * The attributes in inodes and on blocks have a different header; the entries
   * are stored in the same format:
   *
   *   +------------------+
   *   | header           |
   *   | entry 1          | |
   *   | entry 2          | | growing downwards
   *   | entry 3          | v
   *   | four null bytes  |
   *   | . . .            |
   *   | value 1          | ^
   *   | value 3          | | growing upwards
   *   | value 2          | |
   *   +------------------+
   *
   * The header is followed by multiple entry descriptors. In disk blocks, the
   * entry descriptors are kept sorted. In inodes, they are unsorted. The
   * attribute values are aligned to the end of the block in no specific order.
   *
   * Locking strategy
   * ----------------
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
46
   * EXT4_I(inode)->i_file_acl is protected by EXT4_I(inode)->xattr_sem.
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
47
48
49
50
51
52
53
54
55
   * EA blocks are only changed if they are exclusive to an inode, so
   * holding xattr_sem also means that nothing but the EA block's reference
   * count can change. Multiple writers to the same block are synchronized
   * by the buffer lock.
   */
  
  #include <linux/init.h>
  #include <linux/fs.h>
  #include <linux/slab.h>
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
56
57
58
  #include <linux/mbcache.h>
  #include <linux/quotaops.h>
  #include <linux/rwsem.h>
3dcf54515   Christoph Hellwig   ext4: move header...
59
60
  #include "ext4_jbd2.h"
  #include "ext4.h"
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
61
62
  #include "xattr.h"
  #include "acl.h"
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
63
64
  #define BHDR(bh) ((struct ext4_xattr_header *)((bh)->b_data))
  #define ENTRY(ptr) ((struct ext4_xattr_entry *)(ptr))
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
65
66
  #define BFIRST(bh) ENTRY(BHDR(bh)+1)
  #define IS_LAST_ENTRY(entry) (*(__u32 *)(entry) == 0)
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
67
  #ifdef EXT4_XATTR_DEBUG
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
  # define ea_idebug(inode, f...) do { \
  		printk(KERN_DEBUG "inode %s:%lu: ", \
  			inode->i_sb->s_id, inode->i_ino); \
  		printk(f); \
  		printk("
  "); \
  	} while (0)
  # define ea_bdebug(bh, f...) do { \
  		char b[BDEVNAME_SIZE]; \
  		printk(KERN_DEBUG "block %s:%lu: ", \
  			bdevname(bh->b_bdev, b), \
  			(unsigned long) bh->b_blocknr); \
  		printk(f); \
  		printk("
  "); \
  	} while (0)
  #else
  # define ea_idebug(f...)
  # define ea_bdebug(f...)
  #endif
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
88
89
90
  static void ext4_xattr_cache_insert(struct buffer_head *);
  static struct buffer_head *ext4_xattr_cache_find(struct inode *,
  						 struct ext4_xattr_header *,
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
91
  						 struct mb_cache_entry **);
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
92
93
  static void ext4_xattr_rehash(struct ext4_xattr_header *,
  			      struct ext4_xattr_entry *);
431547b3c   Christoph Hellwig   sanitize xattr ha...
94
  static int ext4_xattr_list(struct dentry *dentry, char *buffer,
d3a95d477   Mingming Cao   ext4: make ext4_x...
95
  			   size_t buffer_size);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
96

617ba13b3   Mingming Cao   [PATCH] ext4: ren...
97
  static struct mb_cache *ext4_xattr_cache;
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
98

11e275280   Stephen Hemminger   ext4: constify xa...
99
  static const struct xattr_handler *ext4_xattr_handler_map[] = {
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
100
  	[EXT4_XATTR_INDEX_USER]		     = &ext4_xattr_user_handler,
03010a335   Theodore Ts'o   ext4: Rename ext4...
101
  #ifdef CONFIG_EXT4_FS_POSIX_ACL
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
102
103
  	[EXT4_XATTR_INDEX_POSIX_ACL_ACCESS]  = &ext4_xattr_acl_access_handler,
  	[EXT4_XATTR_INDEX_POSIX_ACL_DEFAULT] = &ext4_xattr_acl_default_handler,
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
104
  #endif
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
105
  	[EXT4_XATTR_INDEX_TRUSTED]	     = &ext4_xattr_trusted_handler,
03010a335   Theodore Ts'o   ext4: Rename ext4...
106
  #ifdef CONFIG_EXT4_FS_SECURITY
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
107
  	[EXT4_XATTR_INDEX_SECURITY]	     = &ext4_xattr_security_handler,
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
108
109
  #endif
  };
11e275280   Stephen Hemminger   ext4: constify xa...
110
  const struct xattr_handler *ext4_xattr_handlers[] = {
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
111
112
  	&ext4_xattr_user_handler,
  	&ext4_xattr_trusted_handler,
03010a335   Theodore Ts'o   ext4: Rename ext4...
113
  #ifdef CONFIG_EXT4_FS_POSIX_ACL
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
114
115
  	&ext4_xattr_acl_access_handler,
  	&ext4_xattr_acl_default_handler,
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
116
  #endif
03010a335   Theodore Ts'o   ext4: Rename ext4...
117
  #ifdef CONFIG_EXT4_FS_SECURITY
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
118
  	&ext4_xattr_security_handler,
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
119
120
121
  #endif
  	NULL
  };
11e275280   Stephen Hemminger   ext4: constify xa...
122
  static inline const struct xattr_handler *
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
123
  ext4_xattr_handler(int name_index)
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
124
  {
11e275280   Stephen Hemminger   ext4: constify xa...
125
  	const struct xattr_handler *handler = NULL;
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
126

617ba13b3   Mingming Cao   [PATCH] ext4: ren...
127
128
  	if (name_index > 0 && name_index < ARRAY_SIZE(ext4_xattr_handler_map))
  		handler = ext4_xattr_handler_map[name_index];
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
129
130
131
132
133
134
135
136
137
  	return handler;
  }
  
  /*
   * Inode operation listxattr()
   *
   * dentry->d_inode->i_mutex: don't care
   */
  ssize_t
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
138
  ext4_listxattr(struct dentry *dentry, char *buffer, size_t size)
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
139
  {
431547b3c   Christoph Hellwig   sanitize xattr ha...
140
  	return ext4_xattr_list(dentry, buffer, size);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
141
142
143
  }
  
  static int
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
144
  ext4_xattr_check_names(struct ext4_xattr_entry *entry, void *end)
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
145
146
  {
  	while (!IS_LAST_ENTRY(entry)) {
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
147
  		struct ext4_xattr_entry *next = EXT4_XATTR_NEXT(entry);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
148
149
150
151
152
153
154
155
  		if ((void *)next >= end)
  			return -EIO;
  		entry = next;
  	}
  	return 0;
  }
  
  static inline int
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
156
  ext4_xattr_check_block(struct buffer_head *bh)
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
157
158
  {
  	int error;
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
159
  	if (BHDR(bh)->h_magic != cpu_to_le32(EXT4_XATTR_MAGIC) ||
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
160
161
  	    BHDR(bh)->h_blocks != cpu_to_le32(1))
  		return -EIO;
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
162
  	error = ext4_xattr_check_names(BFIRST(bh), bh->b_data + bh->b_size);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
163
164
165
166
  	return error;
  }
  
  static inline int
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
167
  ext4_xattr_check_entry(struct ext4_xattr_entry *entry, size_t size)
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
168
169
170
171
172
173
174
175
176
177
  {
  	size_t value_size = le32_to_cpu(entry->e_value_size);
  
  	if (entry->e_value_block != 0 || value_size > size ||
  	    le16_to_cpu(entry->e_value_offs) + value_size > size)
  		return -EIO;
  	return 0;
  }
  
  static int
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
178
  ext4_xattr_find_entry(struct ext4_xattr_entry **pentry, int name_index,
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
179
180
  		      const char *name, size_t size, int sorted)
  {
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
181
  	struct ext4_xattr_entry *entry;
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
182
183
184
185
186
187
188
  	size_t name_len;
  	int cmp = 1;
  
  	if (name == NULL)
  		return -EINVAL;
  	name_len = strlen(name);
  	entry = *pentry;
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
189
  	for (; !IS_LAST_ENTRY(entry); entry = EXT4_XATTR_NEXT(entry)) {
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
190
191
192
193
194
195
196
197
198
  		cmp = name_index - entry->e_name_index;
  		if (!cmp)
  			cmp = name_len - entry->e_name_len;
  		if (!cmp)
  			cmp = memcmp(name, entry->e_name, name_len);
  		if (cmp <= 0 && (sorted || cmp == 0))
  			break;
  	}
  	*pentry = entry;
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
199
  	if (!cmp && ext4_xattr_check_entry(entry, size))
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
200
201
202
203
204
  			return -EIO;
  	return cmp ? -ENODATA : 0;
  }
  
  static int
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
205
  ext4_xattr_block_get(struct inode *inode, int name_index, const char *name,
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
206
207
208
  		     void *buffer, size_t buffer_size)
  {
  	struct buffer_head *bh = NULL;
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
209
  	struct ext4_xattr_entry *entry;
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
210
211
212
213
214
215
216
  	size_t size;
  	int error;
  
  	ea_idebug(inode, "name=%d.%s, buffer=%p, buffer_size=%ld",
  		  name_index, name, buffer, (long)buffer_size);
  
  	error = -ENODATA;
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
217
  	if (!EXT4_I(inode)->i_file_acl)
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
218
  		goto cleanup;
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
219
220
  	ea_idebug(inode, "reading block %u", EXT4_I(inode)->i_file_acl);
  	bh = sb_bread(inode->i_sb, EXT4_I(inode)->i_file_acl);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
221
222
223
224
  	if (!bh)
  		goto cleanup;
  	ea_bdebug(bh, "b_count=%d, refcount=%d",
  		atomic_read(&(bh->b_count)), le32_to_cpu(BHDR(bh)->h_refcount));
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
225
  	if (ext4_xattr_check_block(bh)) {
12062dddd   Eric Sandeen   ext4: move __func...
226
  bad_block:
24676da46   Theodore Ts'o   ext4: Convert cal...
227
228
  		EXT4_ERROR_INODE(inode, "bad block %llu",
  				 EXT4_I(inode)->i_file_acl);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
229
230
231
  		error = -EIO;
  		goto cleanup;
  	}
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
232
  	ext4_xattr_cache_insert(bh);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
233
  	entry = BFIRST(bh);
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
234
  	error = ext4_xattr_find_entry(&entry, name_index, name, bh->b_size, 1);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
  	if (error == -EIO)
  		goto bad_block;
  	if (error)
  		goto cleanup;
  	size = le32_to_cpu(entry->e_value_size);
  	if (buffer) {
  		error = -ERANGE;
  		if (size > buffer_size)
  			goto cleanup;
  		memcpy(buffer, bh->b_data + le16_to_cpu(entry->e_value_offs),
  		       size);
  	}
  	error = size;
  
  cleanup:
  	brelse(bh);
  	return error;
  }
  
  static int
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
255
  ext4_xattr_ibody_get(struct inode *inode, int name_index, const char *name,
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
256
257
  		     void *buffer, size_t buffer_size)
  {
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
258
259
260
261
  	struct ext4_xattr_ibody_header *header;
  	struct ext4_xattr_entry *entry;
  	struct ext4_inode *raw_inode;
  	struct ext4_iloc iloc;
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
262
263
264
  	size_t size;
  	void *end;
  	int error;
19f5fb7ad   Theodore Ts'o   ext4: Use bitops ...
265
  	if (!ext4_test_inode_state(inode, EXT4_STATE_XATTR))
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
266
  		return -ENODATA;
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
267
  	error = ext4_get_inode_loc(inode, &iloc);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
268
269
  	if (error)
  		return error;
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
270
  	raw_inode = ext4_raw_inode(&iloc);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
271
272
  	header = IHDR(inode, raw_inode);
  	entry = IFIRST(header);
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
273
274
  	end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size;
  	error = ext4_xattr_check_names(entry, end);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
275
276
  	if (error)
  		goto cleanup;
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
277
  	error = ext4_xattr_find_entry(&entry, name_index, name,
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
  				      end - (void *)entry, 0);
  	if (error)
  		goto cleanup;
  	size = le32_to_cpu(entry->e_value_size);
  	if (buffer) {
  		error = -ERANGE;
  		if (size > buffer_size)
  			goto cleanup;
  		memcpy(buffer, (void *)IFIRST(header) +
  		       le16_to_cpu(entry->e_value_offs), size);
  	}
  	error = size;
  
  cleanup:
  	brelse(iloc.bh);
  	return error;
  }
  
  /*
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
297
   * ext4_xattr_get()
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
298
299
300
301
302
303
304
305
306
   *
   * Copy an extended attribute into the buffer
   * provided, or compute the buffer size required.
   * Buffer is NULL to compute the size of the buffer required.
   *
   * Returns a negative error number on failure, or the number of bytes
   * used / required on success.
   */
  int
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
307
  ext4_xattr_get(struct inode *inode, int name_index, const char *name,
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
308
309
310
  	       void *buffer, size_t buffer_size)
  {
  	int error;
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
311
312
  	down_read(&EXT4_I(inode)->xattr_sem);
  	error = ext4_xattr_ibody_get(inode, name_index, name, buffer,
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
313
314
  				     buffer_size);
  	if (error == -ENODATA)
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
315
  		error = ext4_xattr_block_get(inode, name_index, name, buffer,
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
316
  					     buffer_size);
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
317
  	up_read(&EXT4_I(inode)->xattr_sem);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
318
319
320
321
  	return error;
  }
  
  static int
431547b3c   Christoph Hellwig   sanitize xattr ha...
322
  ext4_xattr_list_entries(struct dentry *dentry, struct ext4_xattr_entry *entry,
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
323
324
325
  			char *buffer, size_t buffer_size)
  {
  	size_t rest = buffer_size;
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
326
  	for (; !IS_LAST_ENTRY(entry); entry = EXT4_XATTR_NEXT(entry)) {
11e275280   Stephen Hemminger   ext4: constify xa...
327
  		const struct xattr_handler *handler =
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
328
  			ext4_xattr_handler(entry->e_name_index);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
329
330
  
  		if (handler) {
431547b3c   Christoph Hellwig   sanitize xattr ha...
331
  			size_t size = handler->list(dentry, buffer, rest,
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
332
  						    entry->e_name,
431547b3c   Christoph Hellwig   sanitize xattr ha...
333
334
  						    entry->e_name_len,
  						    handler->flags);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
335
336
337
338
339
340
341
342
343
344
345
346
  			if (buffer) {
  				if (size > rest)
  					return -ERANGE;
  				buffer += size;
  			}
  			rest -= size;
  		}
  	}
  	return buffer_size - rest;
  }
  
  static int
431547b3c   Christoph Hellwig   sanitize xattr ha...
347
  ext4_xattr_block_list(struct dentry *dentry, char *buffer, size_t buffer_size)
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
348
  {
431547b3c   Christoph Hellwig   sanitize xattr ha...
349
  	struct inode *inode = dentry->d_inode;
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
350
351
352
353
354
355
356
  	struct buffer_head *bh = NULL;
  	int error;
  
  	ea_idebug(inode, "buffer=%p, buffer_size=%ld",
  		  buffer, (long)buffer_size);
  
  	error = 0;
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
357
  	if (!EXT4_I(inode)->i_file_acl)
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
358
  		goto cleanup;
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
359
360
  	ea_idebug(inode, "reading block %u", EXT4_I(inode)->i_file_acl);
  	bh = sb_bread(inode->i_sb, EXT4_I(inode)->i_file_acl);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
361
362
363
364
365
  	error = -EIO;
  	if (!bh)
  		goto cleanup;
  	ea_bdebug(bh, "b_count=%d, refcount=%d",
  		atomic_read(&(bh->b_count)), le32_to_cpu(BHDR(bh)->h_refcount));
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
366
  	if (ext4_xattr_check_block(bh)) {
24676da46   Theodore Ts'o   ext4: Convert cal...
367
368
  		EXT4_ERROR_INODE(inode, "bad block %llu",
  				 EXT4_I(inode)->i_file_acl);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
369
370
371
  		error = -EIO;
  		goto cleanup;
  	}
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
372
  	ext4_xattr_cache_insert(bh);
431547b3c   Christoph Hellwig   sanitize xattr ha...
373
  	error = ext4_xattr_list_entries(dentry, BFIRST(bh), buffer, buffer_size);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
374
375
376
377
378
379
380
381
  
  cleanup:
  	brelse(bh);
  
  	return error;
  }
  
  static int
431547b3c   Christoph Hellwig   sanitize xattr ha...
382
  ext4_xattr_ibody_list(struct dentry *dentry, char *buffer, size_t buffer_size)
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
383
  {
431547b3c   Christoph Hellwig   sanitize xattr ha...
384
  	struct inode *inode = dentry->d_inode;
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
385
386
387
  	struct ext4_xattr_ibody_header *header;
  	struct ext4_inode *raw_inode;
  	struct ext4_iloc iloc;
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
388
389
  	void *end;
  	int error;
19f5fb7ad   Theodore Ts'o   ext4: Use bitops ...
390
  	if (!ext4_test_inode_state(inode, EXT4_STATE_XATTR))
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
391
  		return 0;
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
392
  	error = ext4_get_inode_loc(inode, &iloc);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
393
394
  	if (error)
  		return error;
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
395
  	raw_inode = ext4_raw_inode(&iloc);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
396
  	header = IHDR(inode, raw_inode);
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
397
398
  	end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size;
  	error = ext4_xattr_check_names(IFIRST(header), end);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
399
400
  	if (error)
  		goto cleanup;
431547b3c   Christoph Hellwig   sanitize xattr ha...
401
  	error = ext4_xattr_list_entries(dentry, IFIRST(header),
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
402
403
404
405
406
407
408
409
  					buffer, buffer_size);
  
  cleanup:
  	brelse(iloc.bh);
  	return error;
  }
  
  /*
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
410
   * ext4_xattr_list()
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
411
412
413
414
415
416
417
418
   *
   * Copy a list of attribute names into the buffer
   * provided, or compute the buffer size required.
   * Buffer is NULL to compute the size of the buffer required.
   *
   * Returns a negative error number on failure, or the number of bytes
   * used / required on success.
   */
d3a95d477   Mingming Cao   ext4: make ext4_x...
419
  static int
431547b3c   Christoph Hellwig   sanitize xattr ha...
420
  ext4_xattr_list(struct dentry *dentry, char *buffer, size_t buffer_size)
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
421
  {
eaeef8671   Theodore Ts'o   ext4: clean up ex...
422
  	int ret, ret2;
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
423

431547b3c   Christoph Hellwig   sanitize xattr ha...
424
  	down_read(&EXT4_I(dentry->d_inode)->xattr_sem);
eaeef8671   Theodore Ts'o   ext4: clean up ex...
425
426
427
428
429
430
  	ret = ret2 = ext4_xattr_ibody_list(dentry, buffer, buffer_size);
  	if (ret < 0)
  		goto errout;
  	if (buffer) {
  		buffer += ret;
  		buffer_size -= ret;
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
431
  	}
eaeef8671   Theodore Ts'o   ext4: clean up ex...
432
433
434
435
436
  	ret = ext4_xattr_block_list(dentry, buffer, buffer_size);
  	if (ret < 0)
  		goto errout;
  	ret += ret2;
  errout:
431547b3c   Christoph Hellwig   sanitize xattr ha...
437
  	up_read(&EXT4_I(dentry->d_inode)->xattr_sem);
eaeef8671   Theodore Ts'o   ext4: clean up ex...
438
  	return ret;
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
439
440
441
  }
  
  /*
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
442
   * If the EXT4_FEATURE_COMPAT_EXT_ATTR feature of this file system is
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
443
444
   * not set, set it.
   */
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
445
  static void ext4_xattr_update_super_block(handle_t *handle,
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
446
447
  					  struct super_block *sb)
  {
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
448
  	if (EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_EXT_ATTR))
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
449
  		return;
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
450
  	if (ext4_journal_get_write_access(handle, EXT4_SB(sb)->s_sbh) == 0) {
ed2908f31   Andreas Gruenbacher   [PATCH] Remove su...
451
  		EXT4_SET_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_EXT_ATTR);
a0375156c   Theodore Ts'o   ext4: Clean up s_...
452
  		ext4_handle_dirty_super(handle, sb);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
453
  	}
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
454
455
456
457
458
459
460
  }
  
  /*
   * Release the xattr block BH: If the reference count is > 1, decrement
   * it; otherwise free the block.
   */
  static void
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
461
  ext4_xattr_release_block(handle_t *handle, struct inode *inode,
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
462
463
464
  			 struct buffer_head *bh)
  {
  	struct mb_cache_entry *ce = NULL;
8a2bfdcbf   Mingming Cao   [PATCH] ext[34]: ...
465
  	int error = 0;
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
466

617ba13b3   Mingming Cao   [PATCH] ext4: ren...
467
  	ce = mb_cache_entry_get(ext4_xattr_cache, bh->b_bdev, bh->b_blocknr);
8a2bfdcbf   Mingming Cao   [PATCH] ext[34]: ...
468
469
470
471
472
  	error = ext4_journal_get_write_access(handle, bh);
  	if (error)
  		goto out;
  
  	lock_buffer(bh);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
473
474
475
476
  	if (BHDR(bh)->h_refcount == cpu_to_le32(1)) {
  		ea_bdebug(bh, "refcount now=0; freeing");
  		if (ce)
  			mb_cache_entry_free(ce);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
477
  		get_bh(bh);
e6362609b   Theodore Ts'o   ext4: call ext4_f...
478
479
480
  		ext4_free_blocks(handle, inode, bh, 0, 1,
  				 EXT4_FREE_BLOCKS_METADATA |
  				 EXT4_FREE_BLOCKS_FORGET);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
481
  	} else {
e8546d061   Marcin Slusarz   ext4: le*_add_cpu...
482
  		le32_add_cpu(&BHDR(bh)->h_refcount, -1);
0390131ba   Frank Mayhar   ext4: Allow ext4 ...
483
  		error = ext4_handle_dirty_metadata(handle, inode, bh);
8a2bfdcbf   Mingming Cao   [PATCH] ext[34]: ...
484
  		if (IS_SYNC(inode))
0390131ba   Frank Mayhar   ext4: Allow ext4 ...
485
  			ext4_handle_sync(handle);
5dd4056db   Christoph Hellwig   dquot: cleanup sp...
486
  		dquot_free_block(inode, 1);
8a2bfdcbf   Mingming Cao   [PATCH] ext[34]: ...
487
488
  		ea_bdebug(bh, "refcount now=%d; releasing",
  			  le32_to_cpu(BHDR(bh)->h_refcount));
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
489
490
491
  		if (ce)
  			mb_cache_entry_release(ce);
  	}
8a2bfdcbf   Mingming Cao   [PATCH] ext[34]: ...
492
493
494
495
  	unlock_buffer(bh);
  out:
  	ext4_std_error(inode->i_sb, error);
  	return;
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
496
  }
6dd4ee7ca   Kalpak Shah   ext4: Expand extr...
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
  /*
   * Find the available free space for EAs. This also returns the total number of
   * bytes used by EA entries.
   */
  static size_t ext4_xattr_free_space(struct ext4_xattr_entry *last,
  				    size_t *min_offs, void *base, int *total)
  {
  	for (; !IS_LAST_ENTRY(last); last = EXT4_XATTR_NEXT(last)) {
  		*total += EXT4_XATTR_LEN(last->e_name_len);
  		if (!last->e_value_block && last->e_value_size) {
  			size_t offs = le16_to_cpu(last->e_value_offs);
  			if (offs < *min_offs)
  				*min_offs = offs;
  		}
  	}
  	return (*min_offs - ((void *)last - base) - sizeof(__u32));
  }
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
514
  struct ext4_xattr_info {
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
515
516
517
518
519
  	int name_index;
  	const char *name;
  	const void *value;
  	size_t value_len;
  };
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
520
521
  struct ext4_xattr_search {
  	struct ext4_xattr_entry *first;
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
522
523
  	void *base;
  	void *end;
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
524
  	struct ext4_xattr_entry *here;
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
525
526
527
528
  	int not_found;
  };
  
  static int
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
529
  ext4_xattr_set_entry(struct ext4_xattr_info *i, struct ext4_xattr_search *s)
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
530
  {
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
531
  	struct ext4_xattr_entry *last;
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
532
533
534
535
  	size_t free, min_offs = s->end - s->base, name_len = strlen(i->name);
  
  	/* Compute min_offs and last. */
  	last = s->first;
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
536
  	for (; !IS_LAST_ENTRY(last); last = EXT4_XATTR_NEXT(last)) {
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
537
538
539
540
541
542
543
544
545
546
  		if (!last->e_value_block && last->e_value_size) {
  			size_t offs = le16_to_cpu(last->e_value_offs);
  			if (offs < min_offs)
  				min_offs = offs;
  		}
  	}
  	free = min_offs - ((void *)last - s->base) - sizeof(__u32);
  	if (!s->not_found) {
  		if (!s->here->e_value_block && s->here->e_value_size) {
  			size_t size = le32_to_cpu(s->here->e_value_size);
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
547
  			free += EXT4_XATTR_SIZE(size);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
548
  		}
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
549
  		free += EXT4_XATTR_LEN(name_len);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
550
551
  	}
  	if (i->value) {
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
552
553
554
  		if (free < EXT4_XATTR_SIZE(i->value_len) ||
  		    free < EXT4_XATTR_LEN(name_len) +
  			   EXT4_XATTR_SIZE(i->value_len))
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
555
556
557
558
559
  			return -ENOSPC;
  	}
  
  	if (i->value && s->not_found) {
  		/* Insert the new name. */
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
560
  		size_t size = EXT4_XATTR_LEN(name_len);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
561
562
563
564
565
566
567
568
569
570
571
  		size_t rest = (void *)last - (void *)s->here + sizeof(__u32);
  		memmove((void *)s->here + size, s->here, rest);
  		memset(s->here, 0, size);
  		s->here->e_name_index = i->name_index;
  		s->here->e_name_len = name_len;
  		memcpy(s->here->e_name, i->name, name_len);
  	} else {
  		if (!s->here->e_value_block && s->here->e_value_size) {
  			void *first_val = s->base + min_offs;
  			size_t offs = le16_to_cpu(s->here->e_value_offs);
  			void *val = s->base + offs;
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
572
  			size_t size = EXT4_XATTR_SIZE(
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
573
  				le32_to_cpu(s->here->e_value_size));
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
574
  			if (i->value && size == EXT4_XATTR_SIZE(i->value_len)) {
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
575
576
577
578
  				/* The old and the new value have the same
  				   size. Just replace. */
  				s->here->e_value_size =
  					cpu_to_le32(i->value_len);
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
579
580
  				memset(val + size - EXT4_XATTR_PAD, 0,
  				       EXT4_XATTR_PAD); /* Clear pad bytes. */
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
  				memcpy(val, i->value, i->value_len);
  				return 0;
  			}
  
  			/* Remove the old value. */
  			memmove(first_val + size, first_val, val - first_val);
  			memset(first_val, 0, size);
  			s->here->e_value_size = 0;
  			s->here->e_value_offs = 0;
  			min_offs += size;
  
  			/* Adjust all value offsets. */
  			last = s->first;
  			while (!IS_LAST_ENTRY(last)) {
  				size_t o = le16_to_cpu(last->e_value_offs);
  				if (!last->e_value_block &&
  				    last->e_value_size && o < offs)
  					last->e_value_offs =
  						cpu_to_le16(o + size);
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
600
  				last = EXT4_XATTR_NEXT(last);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
601
602
603
604
  			}
  		}
  		if (!i->value) {
  			/* Remove the old name. */
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
605
  			size_t size = EXT4_XATTR_LEN(name_len);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
606
607
608
609
610
611
612
613
614
615
616
  			last = ENTRY((void *)last - size);
  			memmove(s->here, (void *)s->here + size,
  				(void *)last - (void *)s->here + sizeof(__u32));
  			memset(last, 0, size);
  		}
  	}
  
  	if (i->value) {
  		/* Insert the new value. */
  		s->here->e_value_size = cpu_to_le32(i->value_len);
  		if (i->value_len) {
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
617
  			size_t size = EXT4_XATTR_SIZE(i->value_len);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
618
619
  			void *val = s->base + min_offs - size;
  			s->here->e_value_offs = cpu_to_le16(min_offs - size);
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
620
621
  			memset(val + size - EXT4_XATTR_PAD, 0,
  			       EXT4_XATTR_PAD); /* Clear the pad bytes. */
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
622
623
624
625
626
  			memcpy(val, i->value, i->value_len);
  		}
  	}
  	return 0;
  }
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
627
628
  struct ext4_xattr_block_find {
  	struct ext4_xattr_search s;
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
629
630
631
632
  	struct buffer_head *bh;
  };
  
  static int
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
633
634
  ext4_xattr_block_find(struct inode *inode, struct ext4_xattr_info *i,
  		      struct ext4_xattr_block_find *bs)
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
635
636
637
638
639
640
  {
  	struct super_block *sb = inode->i_sb;
  	int error;
  
  	ea_idebug(inode, "name=%d.%s, value=%p, value_len=%ld",
  		  i->name_index, i->name, i->value, (long)i->value_len);
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
641
  	if (EXT4_I(inode)->i_file_acl) {
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
642
  		/* The inode already has an extended attribute block. */
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
643
  		bs->bh = sb_bread(sb, EXT4_I(inode)->i_file_acl);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
644
645
646
647
648
649
  		error = -EIO;
  		if (!bs->bh)
  			goto cleanup;
  		ea_bdebug(bs->bh, "b_count=%d, refcount=%d",
  			atomic_read(&(bs->bh->b_count)),
  			le32_to_cpu(BHDR(bs->bh)->h_refcount));
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
650
  		if (ext4_xattr_check_block(bs->bh)) {
24676da46   Theodore Ts'o   ext4: Convert cal...
651
652
  			EXT4_ERROR_INODE(inode, "bad block %llu",
  					 EXT4_I(inode)->i_file_acl);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
653
654
655
656
657
658
659
660
  			error = -EIO;
  			goto cleanup;
  		}
  		/* Find the named attribute. */
  		bs->s.base = BHDR(bs->bh);
  		bs->s.first = BFIRST(bs->bh);
  		bs->s.end = bs->bh->b_data + bs->bh->b_size;
  		bs->s.here = bs->s.first;
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
661
  		error = ext4_xattr_find_entry(&bs->s.here, i->name_index,
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
662
663
664
665
666
667
668
669
670
671
672
673
  					      i->name, bs->bh->b_size, 1);
  		if (error && error != -ENODATA)
  			goto cleanup;
  		bs->s.not_found = error;
  	}
  	error = 0;
  
  cleanup:
  	return error;
  }
  
  static int
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
674
675
676
  ext4_xattr_block_set(handle_t *handle, struct inode *inode,
  		     struct ext4_xattr_info *i,
  		     struct ext4_xattr_block_find *bs)
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
677
678
679
  {
  	struct super_block *sb = inode->i_sb;
  	struct buffer_head *new_bh = NULL;
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
680
  	struct ext4_xattr_search *s = &bs->s;
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
681
  	struct mb_cache_entry *ce = NULL;
8a2bfdcbf   Mingming Cao   [PATCH] ext[34]: ...
682
  	int error = 0;
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
683

617ba13b3   Mingming Cao   [PATCH] ext4: ren...
684
  #define header(x) ((struct ext4_xattr_header *)(x))
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
685
686
687
688
  
  	if (i->value && i->value_len > sb->s_blocksize)
  		return -ENOSPC;
  	if (s->base) {
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
689
  		ce = mb_cache_entry_get(ext4_xattr_cache, bs->bh->b_bdev,
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
690
  					bs->bh->b_blocknr);
8a2bfdcbf   Mingming Cao   [PATCH] ext[34]: ...
691
692
693
694
  		error = ext4_journal_get_write_access(handle, bs->bh);
  		if (error)
  			goto cleanup;
  		lock_buffer(bs->bh);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
695
696
697
698
699
700
  		if (header(s->base)->h_refcount == cpu_to_le32(1)) {
  			if (ce) {
  				mb_cache_entry_free(ce);
  				ce = NULL;
  			}
  			ea_bdebug(bs->bh, "modifying in-place");
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
701
  			error = ext4_xattr_set_entry(i, s);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
702
703
  			if (!error) {
  				if (!IS_LAST_ENTRY(s->first))
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
704
  					ext4_xattr_rehash(header(s->base),
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
705
  							  s->here);
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
706
  				ext4_xattr_cache_insert(bs->bh);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
707
708
709
710
711
  			}
  			unlock_buffer(bs->bh);
  			if (error == -EIO)
  				goto bad_block;
  			if (!error)
0390131ba   Frank Mayhar   ext4: Allow ext4 ...
712
713
714
  				error = ext4_handle_dirty_metadata(handle,
  								   inode,
  								   bs->bh);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
715
716
717
718
719
  			if (error)
  				goto cleanup;
  			goto inserted;
  		} else {
  			int offset = (char *)s->here - bs->bh->b_data;
8a2bfdcbf   Mingming Cao   [PATCH] ext[34]: ...
720
  			unlock_buffer(bs->bh);
537a03103   Amir Goldstein   ext4: unify the e...
721
  			ext4_handle_release_buffer(handle, bs->bh);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
722
723
724
725
726
  			if (ce) {
  				mb_cache_entry_release(ce);
  				ce = NULL;
  			}
  			ea_bdebug(bs->bh, "cloning");
216553c4b   Josef Bacik   ext4: fix wrong g...
727
  			s->base = kmalloc(bs->bh->b_size, GFP_NOFS);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
728
729
730
731
732
733
734
735
736
737
738
  			error = -ENOMEM;
  			if (s->base == NULL)
  				goto cleanup;
  			memcpy(s->base, BHDR(bs->bh), bs->bh->b_size);
  			s->first = ENTRY(header(s->base)+1);
  			header(s->base)->h_refcount = cpu_to_le32(1);
  			s->here = ENTRY(s->base + offset);
  			s->end = s->base + bs->bh->b_size;
  		}
  	} else {
  		/* Allocate a buffer where we construct the new block. */
216553c4b   Josef Bacik   ext4: fix wrong g...
739
  		s->base = kzalloc(sb->s_blocksize, GFP_NOFS);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
740
741
742
743
  		/* assert(header == s->base) */
  		error = -ENOMEM;
  		if (s->base == NULL)
  			goto cleanup;
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
744
  		header(s->base)->h_magic = cpu_to_le32(EXT4_XATTR_MAGIC);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
745
746
747
748
749
750
  		header(s->base)->h_blocks = cpu_to_le32(1);
  		header(s->base)->h_refcount = cpu_to_le32(1);
  		s->first = ENTRY(header(s->base)+1);
  		s->here = ENTRY(header(s->base)+1);
  		s->end = s->base + sb->s_blocksize;
  	}
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
751
  	error = ext4_xattr_set_entry(i, s);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
752
753
754
755
756
  	if (error == -EIO)
  		goto bad_block;
  	if (error)
  		goto cleanup;
  	if (!IS_LAST_ENTRY(s->first))
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
757
  		ext4_xattr_rehash(header(s->base), s->here);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
758
759
760
  
  inserted:
  	if (!IS_LAST_ENTRY(s->first)) {
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
761
  		new_bh = ext4_xattr_cache_find(inode, header(s->base), &ce);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
762
763
764
765
766
767
768
  		if (new_bh) {
  			/* We found an identical block in the cache. */
  			if (new_bh == bs->bh)
  				ea_bdebug(new_bh, "keeping");
  			else {
  				/* The old block is released after updating
  				   the inode. */
5dd4056db   Christoph Hellwig   dquot: cleanup sp...
769
770
  				error = dquot_alloc_block(inode, 1);
  				if (error)
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
771
  					goto cleanup;
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
772
  				error = ext4_journal_get_write_access(handle,
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
773
774
775
776
  								      new_bh);
  				if (error)
  					goto cleanup_dquot;
  				lock_buffer(new_bh);
e8546d061   Marcin Slusarz   ext4: le*_add_cpu...
777
  				le32_add_cpu(&BHDR(new_bh)->h_refcount, 1);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
778
779
780
  				ea_bdebug(new_bh, "reusing; refcount now=%d",
  					le32_to_cpu(BHDR(new_bh)->h_refcount));
  				unlock_buffer(new_bh);
0390131ba   Frank Mayhar   ext4: Allow ext4 ...
781
782
783
  				error = ext4_handle_dirty_metadata(handle,
  								   inode,
  								   new_bh);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
784
785
786
787
788
789
790
791
792
793
794
795
  				if (error)
  					goto cleanup_dquot;
  			}
  			mb_cache_entry_release(ce);
  			ce = NULL;
  		} else if (bs->bh && s->base == bs->bh->b_data) {
  			/* We were modifying this block in-place. */
  			ea_bdebug(bs->bh, "keeping this block");
  			new_bh = bs->bh;
  			get_bh(new_bh);
  		} else {
  			/* We need to allocate a new block */
fb0a387dc   Eric Sandeen   ext4: limit block...
796
797
798
  			ext4_fsblk_t goal, block;
  
  			goal = ext4_group_first_block_no(sb,
d00a6d7b4   Akinobu Mita   ext4: use ext4_gr...
799
  						EXT4_I(inode)->i_block_group);
fb0a387dc   Eric Sandeen   ext4: limit block...
800
801
  
  			/* non-extent files can't have physical blocks past 2^32 */
12e9b8920   Dmitry Monakhov   ext4: Use bitops ...
802
  			if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)))
fb0a387dc   Eric Sandeen   ext4: limit block...
803
  				goal = goal & EXT4_MAX_BLOCK_FILE_PHYS;
6d6a43519   Eric Sandeen   ext4: fix race in...
804
805
806
807
808
  			/*
  			 * take i_data_sem because we will test
  			 * i_delalloc_reserved_flag in ext4_mb_new_blocks
  			 */
  			down_read((&EXT4_I(inode)->i_data_sem));
55f020db6   Allison Henderson   ext4: add flag to...
809
810
  			block = ext4_new_meta_blocks(handle, inode, goal, 0,
  						     NULL, &error);
6d6a43519   Eric Sandeen   ext4: fix race in...
811
  			up_read((&EXT4_I(inode)->i_data_sem));
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
812
813
  			if (error)
  				goto cleanup;
fb0a387dc   Eric Sandeen   ext4: limit block...
814

12e9b8920   Dmitry Monakhov   ext4: Use bitops ...
815
  			if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)))
fb0a387dc   Eric Sandeen   ext4: limit block...
816
  				BUG_ON(block > EXT4_MAX_BLOCK_FILE_PHYS);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
817
818
819
820
821
  			ea_idebug(inode, "creating block %d", block);
  
  			new_bh = sb_getblk(sb, block);
  			if (!new_bh) {
  getblk_failed:
7dc576158   Peter Huewe   ext4: Fix sparse ...
822
  				ext4_free_blocks(handle, inode, NULL, block, 1,
e6362609b   Theodore Ts'o   ext4: call ext4_f...
823
  						 EXT4_FREE_BLOCKS_METADATA);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
824
825
826
827
  				error = -EIO;
  				goto cleanup;
  			}
  			lock_buffer(new_bh);
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
828
  			error = ext4_journal_get_create_access(handle, new_bh);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
829
830
831
832
833
834
835
  			if (error) {
  				unlock_buffer(new_bh);
  				goto getblk_failed;
  			}
  			memcpy(new_bh->b_data, s->base, new_bh->b_size);
  			set_buffer_uptodate(new_bh);
  			unlock_buffer(new_bh);
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
836
  			ext4_xattr_cache_insert(new_bh);
0390131ba   Frank Mayhar   ext4: Allow ext4 ...
837
838
  			error = ext4_handle_dirty_metadata(handle,
  							   inode, new_bh);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
839
840
841
842
843
844
  			if (error)
  				goto cleanup;
  		}
  	}
  
  	/* Update the inode. */
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
845
  	EXT4_I(inode)->i_file_acl = new_bh ? new_bh->b_blocknr : 0;
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
846
847
848
  
  	/* Drop the previous xattr block. */
  	if (bs->bh && bs->bh != new_bh)
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
849
  		ext4_xattr_release_block(handle, inode, bs->bh);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
850
851
852
853
854
855
856
857
858
859
860
861
  	error = 0;
  
  cleanup:
  	if (ce)
  		mb_cache_entry_release(ce);
  	brelse(new_bh);
  	if (!(bs->bh && s->base == bs->bh->b_data))
  		kfree(s->base);
  
  	return error;
  
  cleanup_dquot:
5dd4056db   Christoph Hellwig   dquot: cleanup sp...
862
  	dquot_free_block(inode, 1);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
863
864
865
  	goto cleanup;
  
  bad_block:
24676da46   Theodore Ts'o   ext4: Convert cal...
866
867
  	EXT4_ERROR_INODE(inode, "bad block %llu",
  			 EXT4_I(inode)->i_file_acl);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
868
869
870
871
  	goto cleanup;
  
  #undef header
  }
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
872
873
874
  struct ext4_xattr_ibody_find {
  	struct ext4_xattr_search s;
  	struct ext4_iloc iloc;
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
875
876
877
  };
  
  static int
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
878
879
  ext4_xattr_ibody_find(struct inode *inode, struct ext4_xattr_info *i,
  		      struct ext4_xattr_ibody_find *is)
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
880
  {
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
881
882
  	struct ext4_xattr_ibody_header *header;
  	struct ext4_inode *raw_inode;
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
883
  	int error;
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
884
  	if (EXT4_I(inode)->i_extra_isize == 0)
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
885
  		return 0;
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
886
  	raw_inode = ext4_raw_inode(&is->iloc);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
887
888
889
  	header = IHDR(inode, raw_inode);
  	is->s.base = is->s.first = IFIRST(header);
  	is->s.here = is->s.first;
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
890
  	is->s.end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size;
19f5fb7ad   Theodore Ts'o   ext4: Use bitops ...
891
  	if (ext4_test_inode_state(inode, EXT4_STATE_XATTR)) {
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
892
  		error = ext4_xattr_check_names(IFIRST(header), is->s.end);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
893
894
895
  		if (error)
  			return error;
  		/* Find the named attribute. */
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
896
  		error = ext4_xattr_find_entry(&is->s.here, i->name_index,
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
897
898
899
900
901
902
903
904
905
906
  					      i->name, is->s.end -
  					      (void *)is->s.base, 0);
  		if (error && error != -ENODATA)
  			return error;
  		is->s.not_found = error;
  	}
  	return 0;
  }
  
  static int
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
907
908
909
  ext4_xattr_ibody_set(handle_t *handle, struct inode *inode,
  		     struct ext4_xattr_info *i,
  		     struct ext4_xattr_ibody_find *is)
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
910
  {
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
911
912
  	struct ext4_xattr_ibody_header *header;
  	struct ext4_xattr_search *s = &is->s;
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
913
  	int error;
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
914
  	if (EXT4_I(inode)->i_extra_isize == 0)
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
915
  		return -ENOSPC;
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
916
  	error = ext4_xattr_set_entry(i, s);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
917
918
  	if (error)
  		return error;
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
919
  	header = IHDR(inode, ext4_raw_inode(&is->iloc));
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
920
  	if (!IS_LAST_ENTRY(s->first)) {
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
921
  		header->h_magic = cpu_to_le32(EXT4_XATTR_MAGIC);
19f5fb7ad   Theodore Ts'o   ext4: Use bitops ...
922
  		ext4_set_inode_state(inode, EXT4_STATE_XATTR);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
923
924
  	} else {
  		header->h_magic = cpu_to_le32(0);
19f5fb7ad   Theodore Ts'o   ext4: Use bitops ...
925
  		ext4_clear_inode_state(inode, EXT4_STATE_XATTR);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
926
927
928
929
930
  	}
  	return 0;
  }
  
  /*
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
931
   * ext4_xattr_set_handle()
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
932
   *
6e9510b0e   Wang Sheng-Hui   ext2,ext3,ext4: c...
933
   * Create, replace or remove an extended attribute for this inode.  Value
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
934
935
936
937
938
939
940
941
942
   * is NULL to remove an existing extended attribute, and non-NULL to
   * either replace an existing extended attribute, or create a new extended
   * attribute. The flags XATTR_REPLACE and XATTR_CREATE
   * specify that an extended attribute must exist and must not exist
   * previous to the call, respectively.
   *
   * Returns 0, or a negative error number on failure.
   */
  int
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
943
  ext4_xattr_set_handle(handle_t *handle, struct inode *inode, int name_index,
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
944
945
946
  		      const char *name, const void *value, size_t value_len,
  		      int flags)
  {
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
947
  	struct ext4_xattr_info i = {
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
948
949
950
951
952
953
  		.name_index = name_index,
  		.name = name,
  		.value = value,
  		.value_len = value_len,
  
  	};
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
954
  	struct ext4_xattr_ibody_find is = {
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
955
956
  		.s = { .not_found = -ENODATA, },
  	};
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
957
  	struct ext4_xattr_block_find bs = {
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
958
959
  		.s = { .not_found = -ENODATA, },
  	};
4d20c685f   Kalpak Shah   ext4: fix xattr d...
960
  	unsigned long no_expand;
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
961
962
963
964
965
966
  	int error;
  
  	if (!name)
  		return -EINVAL;
  	if (strlen(name) > 255)
  		return -ERANGE;
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
967
  	down_write(&EXT4_I(inode)->xattr_sem);
19f5fb7ad   Theodore Ts'o   ext4: Use bitops ...
968
969
  	no_expand = ext4_test_inode_state(inode, EXT4_STATE_NO_EXPAND);
  	ext4_set_inode_state(inode, EXT4_STATE_NO_EXPAND);
4d20c685f   Kalpak Shah   ext4: fix xattr d...
970

665436175   Eric Sandeen   ext4: use ext4_re...
971
  	error = ext4_reserve_inode_write(handle, inode, &is.iloc);
86ebfd08a   Eric Sandeen   ext4: journal all...
972
973
  	if (error)
  		goto cleanup;
19f5fb7ad   Theodore Ts'o   ext4: Use bitops ...
974
  	if (ext4_test_inode_state(inode, EXT4_STATE_NEW)) {
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
975
976
  		struct ext4_inode *raw_inode = ext4_raw_inode(&is.iloc);
  		memset(raw_inode, 0, EXT4_SB(inode->i_sb)->s_inode_size);
19f5fb7ad   Theodore Ts'o   ext4: Use bitops ...
977
  		ext4_clear_inode_state(inode, EXT4_STATE_NEW);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
978
  	}
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
979
  	error = ext4_xattr_ibody_find(inode, &i, &is);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
980
981
982
  	if (error)
  		goto cleanup;
  	if (is.s.not_found)
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
983
  		error = ext4_xattr_block_find(inode, &i, &bs);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
984
985
986
987
988
989
990
991
992
993
994
995
996
997
  	if (error)
  		goto cleanup;
  	if (is.s.not_found && bs.s.not_found) {
  		error = -ENODATA;
  		if (flags & XATTR_REPLACE)
  			goto cleanup;
  		error = 0;
  		if (!value)
  			goto cleanup;
  	} else {
  		error = -EEXIST;
  		if (flags & XATTR_CREATE)
  			goto cleanup;
  	}
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
998
999
  	if (!value) {
  		if (!is.s.not_found)
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
1000
  			error = ext4_xattr_ibody_set(handle, inode, &i, &is);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
1001
  		else if (!bs.s.not_found)
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
1002
  			error = ext4_xattr_block_set(handle, inode, &i, &bs);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
1003
  	} else {
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
1004
  		error = ext4_xattr_ibody_set(handle, inode, &i, &is);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
1005
1006
  		if (!error && !bs.s.not_found) {
  			i.value = NULL;
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
1007
  			error = ext4_xattr_block_set(handle, inode, &i, &bs);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
1008
  		} else if (error == -ENOSPC) {
7e01c8e54   Tiger Yang   ext3/4: fix unini...
1009
1010
1011
1012
1013
  			if (EXT4_I(inode)->i_file_acl && !bs.s.base) {
  				error = ext4_xattr_block_find(inode, &i, &bs);
  				if (error)
  					goto cleanup;
  			}
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
1014
  			error = ext4_xattr_block_set(handle, inode, &i, &bs);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
1015
1016
1017
1018
  			if (error)
  				goto cleanup;
  			if (!is.s.not_found) {
  				i.value = NULL;
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
1019
  				error = ext4_xattr_ibody_set(handle, inode, &i,
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
1020
1021
1022
1023
1024
  							     &is);
  			}
  		}
  	}
  	if (!error) {
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
1025
  		ext4_xattr_update_super_block(handle, inode->i_sb);
ef7f38359   Kalpak Shah   ext4: Add nanosec...
1026
  		inode->i_ctime = ext4_current_time(inode);
6dd4ee7ca   Kalpak Shah   ext4: Expand extr...
1027
  		if (!value)
19f5fb7ad   Theodore Ts'o   ext4: Use bitops ...
1028
  			ext4_clear_inode_state(inode, EXT4_STATE_NO_EXPAND);
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
1029
  		error = ext4_mark_iloc_dirty(handle, inode, &is.iloc);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
1030
  		/*
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
1031
  		 * The bh is consumed by ext4_mark_iloc_dirty, even with
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
1032
1033
1034
1035
  		 * error != 0.
  		 */
  		is.iloc.bh = NULL;
  		if (IS_SYNC(inode))
0390131ba   Frank Mayhar   ext4: Allow ext4 ...
1036
  			ext4_handle_sync(handle);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
1037
1038
1039
1040
1041
  	}
  
  cleanup:
  	brelse(is.iloc.bh);
  	brelse(bs.bh);
4d20c685f   Kalpak Shah   ext4: fix xattr d...
1042
  	if (no_expand == 0)
19f5fb7ad   Theodore Ts'o   ext4: Use bitops ...
1043
  		ext4_clear_inode_state(inode, EXT4_STATE_NO_EXPAND);
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
1044
  	up_write(&EXT4_I(inode)->xattr_sem);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
1045
1046
1047
1048
  	return error;
  }
  
  /*
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
1049
   * ext4_xattr_set()
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
1050
   *
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
1051
   * Like ext4_xattr_set_handle, but start from an inode. This extended
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
1052
1053
1054
1055
1056
   * attribute modification is a filesystem transaction by itself.
   *
   * Returns 0, or a negative error number on failure.
   */
  int
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
1057
  ext4_xattr_set(struct inode *inode, int name_index, const char *name,
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
1058
1059
1060
1061
1062
1063
  	       const void *value, size_t value_len, int flags)
  {
  	handle_t *handle;
  	int error, retries = 0;
  
  retry:
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
1064
  	handle = ext4_journal_start(inode, EXT4_DATA_TRANS_BLOCKS(inode->i_sb));
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
1065
1066
1067
1068
  	if (IS_ERR(handle)) {
  		error = PTR_ERR(handle);
  	} else {
  		int error2;
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
1069
  		error = ext4_xattr_set_handle(handle, inode, name_index, name,
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
1070
  					      value, value_len, flags);
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
1071
  		error2 = ext4_journal_stop(handle);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
1072
  		if (error == -ENOSPC &&
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
1073
  		    ext4_should_retry_alloc(inode->i_sb, &retries))
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
1074
1075
1076
1077
1078
1079
1080
1081
1082
  			goto retry;
  		if (error == 0)
  			error = error2;
  	}
  
  	return error;
  }
  
  /*
6dd4ee7ca   Kalpak Shah   ext4: Expand extr...
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
   * Shift the EA entries in the inode to create space for the increased
   * i_extra_isize.
   */
  static void ext4_xattr_shift_entries(struct ext4_xattr_entry *entry,
  				     int value_offs_shift, void *to,
  				     void *from, size_t n, int blocksize)
  {
  	struct ext4_xattr_entry *last = entry;
  	int new_offs;
  
  	/* Adjust the value offsets of the entries */
  	for (; !IS_LAST_ENTRY(last); last = EXT4_XATTR_NEXT(last)) {
  		if (!last->e_value_block && last->e_value_size) {
  			new_offs = le16_to_cpu(last->e_value_offs) +
  							value_offs_shift;
  			BUG_ON(new_offs + le32_to_cpu(last->e_value_size)
  				 > blocksize);
  			last->e_value_offs = cpu_to_le16(new_offs);
  		}
  	}
  	/* Shift the entries by n bytes */
  	memmove(to, from, n);
  }
  
  /*
   * Expand an inode by new_extra_isize bytes when EAs are present.
   * Returns 0 on success or negative error number on failure.
   */
  int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize,
  			       struct ext4_inode *raw_inode, handle_t *handle)
  {
  	struct ext4_xattr_ibody_header *header;
  	struct ext4_xattr_entry *entry, *last, *first;
  	struct buffer_head *bh = NULL;
  	struct ext4_xattr_ibody_find *is = NULL;
  	struct ext4_xattr_block_find *bs = NULL;
  	char *buffer = NULL, *b_entry_name = NULL;
  	size_t min_offs, free;
  	int total_ino, total_blk;
  	void *base, *start, *end;
  	int extra_isize = 0, error = 0, tried_min_extra_isize = 0;
ac39849dd   Aneesh Kumar K.V   ext4: sparse fixes
1124
  	int s_min_extra_isize = le16_to_cpu(EXT4_SB(inode->i_sb)->s_es->s_min_extra_isize);
6dd4ee7ca   Kalpak Shah   ext4: Expand extr...
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
  
  	down_write(&EXT4_I(inode)->xattr_sem);
  retry:
  	if (EXT4_I(inode)->i_extra_isize >= new_extra_isize) {
  		up_write(&EXT4_I(inode)->xattr_sem);
  		return 0;
  	}
  
  	header = IHDR(inode, raw_inode);
  	entry = IFIRST(header);
  
  	/*
  	 * Check if enough free space is available in the inode to shift the
  	 * entries ahead by new_extra_isize.
  	 */
  
  	base = start = entry;
  	end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size;
  	min_offs = end - base;
  	last = entry;
  	total_ino = sizeof(struct ext4_xattr_ibody_header);
  
  	free = ext4_xattr_free_space(last, &min_offs, base, &total_ino);
  	if (free >= new_extra_isize) {
  		entry = IFIRST(header);
  		ext4_xattr_shift_entries(entry,	EXT4_I(inode)->i_extra_isize
  				- new_extra_isize, (void *)raw_inode +
  				EXT4_GOOD_OLD_INODE_SIZE + new_extra_isize,
  				(void *)header, total_ino,
  				inode->i_sb->s_blocksize);
  		EXT4_I(inode)->i_extra_isize = new_extra_isize;
  		error = 0;
  		goto cleanup;
  	}
  
  	/*
  	 * Enough free space isn't available in the inode, check if
  	 * EA block can hold new_extra_isize bytes.
  	 */
  	if (EXT4_I(inode)->i_file_acl) {
  		bh = sb_bread(inode->i_sb, EXT4_I(inode)->i_file_acl);
  		error = -EIO;
  		if (!bh)
  			goto cleanup;
  		if (ext4_xattr_check_block(bh)) {
24676da46   Theodore Ts'o   ext4: Convert cal...
1170
1171
  			EXT4_ERROR_INODE(inode, "bad block %llu",
  					 EXT4_I(inode)->i_file_acl);
6dd4ee7ca   Kalpak Shah   ext4: Expand extr...
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
  			error = -EIO;
  			goto cleanup;
  		}
  		base = BHDR(bh);
  		first = BFIRST(bh);
  		end = bh->b_data + bh->b_size;
  		min_offs = end - base;
  		free = ext4_xattr_free_space(first, &min_offs, base,
  					     &total_blk);
  		if (free < new_extra_isize) {
  			if (!tried_min_extra_isize && s_min_extra_isize) {
  				tried_min_extra_isize++;
  				new_extra_isize = s_min_extra_isize;
  				brelse(bh);
  				goto retry;
  			}
  			error = -1;
  			goto cleanup;
  		}
  	} else {
  		free = inode->i_sb->s_blocksize;
  	}
  
  	while (new_extra_isize > 0) {
  		size_t offs, size, entry_size;
  		struct ext4_xattr_entry *small_entry = NULL;
  		struct ext4_xattr_info i = {
  			.value = NULL,
  			.value_len = 0,
  		};
  		unsigned int total_size;  /* EA entry size + value size */
  		unsigned int shift_bytes; /* No. of bytes to shift EAs by? */
  		unsigned int min_total_size = ~0U;
  
  		is = kzalloc(sizeof(struct ext4_xattr_ibody_find), GFP_NOFS);
  		bs = kzalloc(sizeof(struct ext4_xattr_block_find), GFP_NOFS);
  		if (!is || !bs) {
  			error = -ENOMEM;
  			goto cleanup;
  		}
  
  		is->s.not_found = -ENODATA;
  		bs->s.not_found = -ENODATA;
  		is->iloc.bh = NULL;
  		bs->bh = NULL;
  
  		last = IFIRST(header);
  		/* Find the entry best suited to be pushed into EA block */
  		entry = NULL;
  		for (; !IS_LAST_ENTRY(last); last = EXT4_XATTR_NEXT(last)) {
  			total_size =
  			EXT4_XATTR_SIZE(le32_to_cpu(last->e_value_size)) +
  					EXT4_XATTR_LEN(last->e_name_len);
  			if (total_size <= free && total_size < min_total_size) {
  				if (total_size < new_extra_isize) {
  					small_entry = last;
  				} else {
  					entry = last;
  					min_total_size = total_size;
  				}
  			}
  		}
  
  		if (entry == NULL) {
  			if (small_entry) {
  				entry = small_entry;
  			} else {
  				if (!tried_min_extra_isize &&
  				    s_min_extra_isize) {
  					tried_min_extra_isize++;
  					new_extra_isize = s_min_extra_isize;
  					goto retry;
  				}
  				error = -1;
  				goto cleanup;
  			}
  		}
  		offs = le16_to_cpu(entry->e_value_offs);
  		size = le32_to_cpu(entry->e_value_size);
  		entry_size = EXT4_XATTR_LEN(entry->e_name_len);
  		i.name_index = entry->e_name_index,
  		buffer = kmalloc(EXT4_XATTR_SIZE(size), GFP_NOFS);
  		b_entry_name = kmalloc(entry->e_name_len + 1, GFP_NOFS);
  		if (!buffer || !b_entry_name) {
  			error = -ENOMEM;
  			goto cleanup;
  		}
  		/* Save the entry name and the entry value */
  		memcpy(buffer, (void *)IFIRST(header) + offs,
  		       EXT4_XATTR_SIZE(size));
  		memcpy(b_entry_name, entry->e_name, entry->e_name_len);
  		b_entry_name[entry->e_name_len] = '\0';
  		i.name = b_entry_name;
  
  		error = ext4_get_inode_loc(inode, &is->iloc);
  		if (error)
  			goto cleanup;
  
  		error = ext4_xattr_ibody_find(inode, &i, is);
  		if (error)
  			goto cleanup;
  
  		/* Remove the chosen entry from the inode */
  		error = ext4_xattr_ibody_set(handle, inode, &i, is);
9aaab0589   Roel Kluin   ext4: add missing...
1276
1277
  		if (error)
  			goto cleanup;
6dd4ee7ca   Kalpak Shah   ext4: Expand extr...
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
  
  		entry = IFIRST(header);
  		if (entry_size + EXT4_XATTR_SIZE(size) >= new_extra_isize)
  			shift_bytes = new_extra_isize;
  		else
  			shift_bytes = entry_size + size;
  		/* Adjust the offsets and shift the remaining entries ahead */
  		ext4_xattr_shift_entries(entry, EXT4_I(inode)->i_extra_isize -
  			shift_bytes, (void *)raw_inode +
  			EXT4_GOOD_OLD_INODE_SIZE + extra_isize + shift_bytes,
  			(void *)header, total_ino - entry_size,
  			inode->i_sb->s_blocksize);
  
  		extra_isize += shift_bytes;
  		new_extra_isize -= shift_bytes;
  		EXT4_I(inode)->i_extra_isize = extra_isize;
  
  		i.name = b_entry_name;
  		i.value = buffer;
ac39849dd   Aneesh Kumar K.V   ext4: sparse fixes
1297
  		i.value_len = size;
6dd4ee7ca   Kalpak Shah   ext4: Expand extr...
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
  		error = ext4_xattr_block_find(inode, &i, bs);
  		if (error)
  			goto cleanup;
  
  		/* Add entry which was removed from the inode into the block */
  		error = ext4_xattr_block_set(handle, inode, &i, bs);
  		if (error)
  			goto cleanup;
  		kfree(b_entry_name);
  		kfree(buffer);
d3533d72e   Julia Lawall   ext4: Eliminate p...
1308
1309
  		b_entry_name = NULL;
  		buffer = NULL;
6dd4ee7ca   Kalpak Shah   ext4: Expand extr...
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
  		brelse(is->iloc.bh);
  		kfree(is);
  		kfree(bs);
  	}
  	brelse(bh);
  	up_write(&EXT4_I(inode)->xattr_sem);
  	return 0;
  
  cleanup:
  	kfree(b_entry_name);
  	kfree(buffer);
  	if (is)
  		brelse(is->iloc.bh);
  	kfree(is);
  	kfree(bs);
  	brelse(bh);
  	up_write(&EXT4_I(inode)->xattr_sem);
  	return error;
  }
  
  
  
  /*
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
1333
   * ext4_xattr_delete_inode()
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
1334
1335
1336
1337
1338
1339
   *
   * Free extended attribute resources associated with this inode. This
   * is called immediately before an inode is freed. We have exclusive
   * access to the inode.
   */
  void
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
1340
  ext4_xattr_delete_inode(handle_t *handle, struct inode *inode)
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
1341
1342
  {
  	struct buffer_head *bh = NULL;
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
1343
  	if (!EXT4_I(inode)->i_file_acl)
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
1344
  		goto cleanup;
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
1345
  	bh = sb_bread(inode->i_sb, EXT4_I(inode)->i_file_acl);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
1346
  	if (!bh) {
24676da46   Theodore Ts'o   ext4: Convert cal...
1347
1348
  		EXT4_ERROR_INODE(inode, "block %llu read error",
  				 EXT4_I(inode)->i_file_acl);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
1349
1350
  		goto cleanup;
  	}
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
1351
  	if (BHDR(bh)->h_magic != cpu_to_le32(EXT4_XATTR_MAGIC) ||
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
1352
  	    BHDR(bh)->h_blocks != cpu_to_le32(1)) {
24676da46   Theodore Ts'o   ext4: Convert cal...
1353
1354
  		EXT4_ERROR_INODE(inode, "bad block %llu",
  				 EXT4_I(inode)->i_file_acl);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
1355
1356
  		goto cleanup;
  	}
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
1357
1358
  	ext4_xattr_release_block(handle, inode, bh);
  	EXT4_I(inode)->i_file_acl = 0;
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
1359
1360
1361
1362
1363
1364
  
  cleanup:
  	brelse(bh);
  }
  
  /*
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
1365
   * ext4_xattr_put_super()
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
1366
1367
1368
1369
   *
   * This is called when a file system is unmounted.
   */
  void
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
1370
  ext4_xattr_put_super(struct super_block *sb)
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
1371
1372
1373
1374
1375
  {
  	mb_cache_shrink(sb->s_bdev);
  }
  
  /*
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
1376
   * ext4_xattr_cache_insert()
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
1377
1378
1379
1380
1381
1382
1383
   *
   * Create a new entry in the extended attribute cache, and insert
   * it unless such an entry is already in the cache.
   *
   * Returns 0, or a negative error number on failure.
   */
  static void
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
1384
  ext4_xattr_cache_insert(struct buffer_head *bh)
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
1385
1386
1387
1388
  {
  	__u32 hash = le32_to_cpu(BHDR(bh)->h_hash);
  	struct mb_cache_entry *ce;
  	int error;
335e92e8a   Jan Kara   vfs: fix possible...
1389
  	ce = mb_cache_entry_alloc(ext4_xattr_cache, GFP_NOFS);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
1390
1391
1392
1393
  	if (!ce) {
  		ea_bdebug(bh, "out of memory");
  		return;
  	}
2aec7c523   Andreas Gruenbacher   mbcache: Remove u...
1394
  	error = mb_cache_entry_insert(ce, bh->b_bdev, bh->b_blocknr, hash);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
  	if (error) {
  		mb_cache_entry_free(ce);
  		if (error == -EBUSY) {
  			ea_bdebug(bh, "already in cache");
  			error = 0;
  		}
  	} else {
  		ea_bdebug(bh, "inserting [%x]", (int)hash);
  		mb_cache_entry_release(ce);
  	}
  }
  
  /*
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
1408
   * ext4_xattr_cmp()
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
1409
1410
1411
1412
1413
1414
1415
   *
   * Compare two extended attribute blocks for equality.
   *
   * Returns 0 if the blocks are equal, 1 if they differ, and
   * a negative error number on errors.
   */
  static int
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
1416
1417
  ext4_xattr_cmp(struct ext4_xattr_header *header1,
  	       struct ext4_xattr_header *header2)
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
1418
  {
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
1419
  	struct ext4_xattr_entry *entry1, *entry2;
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
  
  	entry1 = ENTRY(header1+1);
  	entry2 = ENTRY(header2+1);
  	while (!IS_LAST_ENTRY(entry1)) {
  		if (IS_LAST_ENTRY(entry2))
  			return 1;
  		if (entry1->e_hash != entry2->e_hash ||
  		    entry1->e_name_index != entry2->e_name_index ||
  		    entry1->e_name_len != entry2->e_name_len ||
  		    entry1->e_value_size != entry2->e_value_size ||
  		    memcmp(entry1->e_name, entry2->e_name, entry1->e_name_len))
  			return 1;
  		if (entry1->e_value_block != 0 || entry2->e_value_block != 0)
  			return -EIO;
  		if (memcmp((char *)header1 + le16_to_cpu(entry1->e_value_offs),
  			   (char *)header2 + le16_to_cpu(entry2->e_value_offs),
  			   le32_to_cpu(entry1->e_value_size)))
  			return 1;
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
1438
1439
  		entry1 = EXT4_XATTR_NEXT(entry1);
  		entry2 = EXT4_XATTR_NEXT(entry2);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
1440
1441
1442
1443
1444
1445
1446
  	}
  	if (!IS_LAST_ENTRY(entry2))
  		return 1;
  	return 0;
  }
  
  /*
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
1447
   * ext4_xattr_cache_find()
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
1448
1449
1450
1451
1452
1453
1454
   *
   * Find an identical extended attribute block.
   *
   * Returns a pointer to the block found, or NULL if such a block was
   * not found or an error occurred.
   */
  static struct buffer_head *
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
1455
  ext4_xattr_cache_find(struct inode *inode, struct ext4_xattr_header *header,
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
1456
1457
1458
1459
1460
1461
1462
1463
1464
  		      struct mb_cache_entry **pce)
  {
  	__u32 hash = le32_to_cpu(header->h_hash);
  	struct mb_cache_entry *ce;
  
  	if (!header->h_hash)
  		return NULL;  /* never share */
  	ea_idebug(inode, "looking for cached blocks [%x]", (int)hash);
  again:
2aec7c523   Andreas Gruenbacher   mbcache: Remove u...
1465
1466
  	ce = mb_cache_entry_find_first(ext4_xattr_cache, inode->i_sb->s_bdev,
  				       hash);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
  	while (ce) {
  		struct buffer_head *bh;
  
  		if (IS_ERR(ce)) {
  			if (PTR_ERR(ce) == -EAGAIN)
  				goto again;
  			break;
  		}
  		bh = sb_bread(inode->i_sb, ce->e_block);
  		if (!bh) {
24676da46   Theodore Ts'o   ext4: Convert cal...
1477
1478
  			EXT4_ERROR_INODE(inode, "block %lu read error",
  					 (unsigned long) ce->e_block);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
1479
  		} else if (le32_to_cpu(BHDR(bh)->h_refcount) >=
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
1480
  				EXT4_XATTR_REFCOUNT_MAX) {
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
1481
1482
1483
  			ea_idebug(inode, "block %lu refcount %d>=%d",
  				  (unsigned long) ce->e_block,
  				  le32_to_cpu(BHDR(bh)->h_refcount),
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
1484
1485
  					  EXT4_XATTR_REFCOUNT_MAX);
  		} else if (ext4_xattr_cmp(header, BHDR(bh)) == 0) {
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
1486
1487
1488
1489
  			*pce = ce;
  			return bh;
  		}
  		brelse(bh);
2aec7c523   Andreas Gruenbacher   mbcache: Remove u...
1490
  		ce = mb_cache_entry_find_next(ce, inode->i_sb->s_bdev, hash);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
1491
1492
1493
1494
1495
1496
1497
1498
  	}
  	return NULL;
  }
  
  #define NAME_HASH_SHIFT 5
  #define VALUE_HASH_SHIFT 16
  
  /*
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
1499
   * ext4_xattr_hash_entry()
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
1500
1501
1502
   *
   * Compute the hash of an extended attribute.
   */
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
1503
1504
  static inline void ext4_xattr_hash_entry(struct ext4_xattr_header *header,
  					 struct ext4_xattr_entry *entry)
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
1505
1506
1507
1508
  {
  	__u32 hash = 0;
  	char *name = entry->e_name;
  	int n;
2b2d6d019   Theodore Ts'o   ext4: Cleanup whi...
1509
  	for (n = 0; n < entry->e_name_len; n++) {
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
1510
1511
1512
1513
1514
1515
1516
1517
1518
  		hash = (hash << NAME_HASH_SHIFT) ^
  		       (hash >> (8*sizeof(hash) - NAME_HASH_SHIFT)) ^
  		       *name++;
  	}
  
  	if (entry->e_value_block == 0 && entry->e_value_size != 0) {
  		__le32 *value = (__le32 *)((char *)header +
  			le16_to_cpu(entry->e_value_offs));
  		for (n = (le32_to_cpu(entry->e_value_size) +
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
1519
  		     EXT4_XATTR_ROUND) >> EXT4_XATTR_PAD_BITS; n; n--) {
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
  			hash = (hash << VALUE_HASH_SHIFT) ^
  			       (hash >> (8*sizeof(hash) - VALUE_HASH_SHIFT)) ^
  			       le32_to_cpu(*value++);
  		}
  	}
  	entry->e_hash = cpu_to_le32(hash);
  }
  
  #undef NAME_HASH_SHIFT
  #undef VALUE_HASH_SHIFT
  
  #define BLOCK_HASH_SHIFT 16
  
  /*
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
1534
   * ext4_xattr_rehash()
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
1535
1536
1537
   *
   * Re-compute the extended attribute hash value after an entry has changed.
   */
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
1538
1539
  static void ext4_xattr_rehash(struct ext4_xattr_header *header,
  			      struct ext4_xattr_entry *entry)
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
1540
  {
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
1541
  	struct ext4_xattr_entry *here;
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
1542
  	__u32 hash = 0;
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
1543
  	ext4_xattr_hash_entry(header, entry);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
  	here = ENTRY(header+1);
  	while (!IS_LAST_ENTRY(here)) {
  		if (!here->e_hash) {
  			/* Block is not shared if an entry's hash value == 0 */
  			hash = 0;
  			break;
  		}
  		hash = (hash << BLOCK_HASH_SHIFT) ^
  		       (hash >> (8*sizeof(hash) - BLOCK_HASH_SHIFT)) ^
  		       le32_to_cpu(here->e_hash);
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
1554
  		here = EXT4_XATTR_NEXT(here);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
1555
1556
1557
1558
1559
1560
1561
  	}
  	header->h_hash = cpu_to_le32(hash);
  }
  
  #undef BLOCK_HASH_SHIFT
  
  int __init
5dabfc78d   Theodore Ts'o   ext4: rename {exi...
1562
  ext4_init_xattr(void)
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
1563
  {
2aec7c523   Andreas Gruenbacher   mbcache: Remove u...
1564
  	ext4_xattr_cache = mb_cache_create("ext4_xattr", 6);
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
1565
  	if (!ext4_xattr_cache)
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
1566
1567
1568
1569
1570
  		return -ENOMEM;
  	return 0;
  }
  
  void
5dabfc78d   Theodore Ts'o   ext4: rename {exi...
1571
  ext4_exit_xattr(void)
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
1572
  {
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
1573
1574
1575
  	if (ext4_xattr_cache)
  		mb_cache_destroy(ext4_xattr_cache);
  	ext4_xattr_cache = NULL;
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
1576
  }