Blame view

fs/gfs2/xattr.c 32.9 KB
b3b94faa5   David Teigland   [GFS2] The core o...
1
2
  /*
   * Copyright (C) Sistina Software, Inc.  1997-2003 All rights reserved.
3a8a9a103   Steven Whitehouse   [GFS2] Update cop...
3
   * Copyright (C) 2004-2006 Red Hat, Inc.  All rights reserved.
b3b94faa5   David Teigland   [GFS2] The core o...
4
5
6
   *
   * This copyrighted material is made available to anyone wishing to use,
   * modify, copy, or redistribute it subject to the terms and conditions
e9fc2aa09   Steven Whitehouse   [GFS2] Update cop...
7
   * of the GNU General Public License version 2.
b3b94faa5   David Teigland   [GFS2] The core o...
8
   */
b3b94faa5   David Teigland   [GFS2] The core o...
9
10
11
12
13
  #include <linux/slab.h>
  #include <linux/spinlock.h>
  #include <linux/completion.h>
  #include <linux/buffer_head.h>
  #include <linux/xattr.h>
5c676f6d3   Steven Whitehouse   [GFS2] Macros rem...
14
  #include <linux/gfs2_ondisk.h>
b3b94faa5   David Teigland   [GFS2] The core o...
15
16
17
  #include <asm/uaccess.h>
  
  #include "gfs2.h"
5c676f6d3   Steven Whitehouse   [GFS2] Macros rem...
18
  #include "incore.h"
b3b94faa5   David Teigland   [GFS2] The core o...
19
  #include "acl.h"
307cf6e63   Steven Whitehouse   GFS2: Rename eatt...
20
  #include "xattr.h"
b3b94faa5   David Teigland   [GFS2] The core o...
21
22
23
24
25
26
  #include "glock.h"
  #include "inode.h"
  #include "meta_io.h"
  #include "quota.h"
  #include "rgrp.h"
  #include "trans.h"
5c676f6d3   Steven Whitehouse   [GFS2] Macros rem...
27
  #include "util.h"
b3b94faa5   David Teigland   [GFS2] The core o...
28
29
30
31
32
33
34
35
36
37
  
  /**
   * ea_calc_size - returns the acutal number of bytes the request will take up
   *                (not counting any unstuffed data blocks)
   * @sdp:
   * @er:
   * @size:
   *
   * Returns: 1 if the EA should be stuffed
   */
40b78a322   Steven Whitehouse   GFS2: Clean up of...
38
  static int ea_calc_size(struct gfs2_sbd *sdp, unsigned int nsize, size_t dsize,
b3b94faa5   David Teigland   [GFS2] The core o...
39
40
  			unsigned int *size)
  {
40b78a322   Steven Whitehouse   GFS2: Clean up of...
41
42
43
44
45
46
  	unsigned int jbsize = sdp->sd_jbsize;
  
  	/* Stuffed */
  	*size = ALIGN(sizeof(struct gfs2_ea_header) + nsize + dsize, 8);
  
  	if (*size <= jbsize)
b3b94faa5   David Teigland   [GFS2] The core o...
47
  		return 1;
40b78a322   Steven Whitehouse   GFS2: Clean up of...
48
49
50
  	/* Unstuffed */
  	*size = ALIGN(sizeof(struct gfs2_ea_header) + nsize +
  		      (sizeof(__be64) * DIV_ROUND_UP(dsize, jbsize)), 8);
b3b94faa5   David Teigland   [GFS2] The core o...
51
52
53
  
  	return 0;
  }
40b78a322   Steven Whitehouse   GFS2: Clean up of...
54
  static int ea_check_size(struct gfs2_sbd *sdp, unsigned int nsize, size_t dsize)
b3b94faa5   David Teigland   [GFS2] The core o...
55
56
  {
  	unsigned int size;
40b78a322   Steven Whitehouse   GFS2: Clean up of...
57
  	if (dsize > GFS2_EA_MAX_DATA_LEN)
b3b94faa5   David Teigland   [GFS2] The core o...
58
  		return -ERANGE;
40b78a322   Steven Whitehouse   GFS2: Clean up of...
59
  	ea_calc_size(sdp, nsize, dsize, &size);
b3b94faa5   David Teigland   [GFS2] The core o...
60
61
62
63
64
65
66
  
  	/* This can only happen with 512 byte blocks */
  	if (size > sdp->sd_jbsize)
  		return -ERANGE;
  
  	return 0;
  }
cca195c5c   Steven Whitehouse   [GFS2] Extended a...
67
  typedef int (*ea_call_t) (struct gfs2_inode *ip, struct buffer_head *bh,
b3b94faa5   David Teigland   [GFS2] The core o...
68
  			  struct gfs2_ea_header *ea,
cca195c5c   Steven Whitehouse   [GFS2] Extended a...
69
  			  struct gfs2_ea_header *prev, void *private);
b3b94faa5   David Teigland   [GFS2] The core o...
70
71
72
73
74
75
  
  static int ea_foreach_i(struct gfs2_inode *ip, struct buffer_head *bh,
  			ea_call_t ea_call, void *data)
  {
  	struct gfs2_ea_header *ea, *prev = NULL;
  	int error = 0;
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
76
  	if (gfs2_metatype_check(GFS2_SB(&ip->i_inode), bh, GFS2_METATYPE_EA))
b3b94faa5   David Teigland   [GFS2] The core o...
77
78
79
80
81
  		return -EIO;
  
  	for (ea = GFS2_EA_BH2FIRST(bh);; prev = ea, ea = GFS2_EA2NEXT(ea)) {
  		if (!GFS2_EA_REC_LEN(ea))
  			goto fail;
cca195c5c   Steven Whitehouse   [GFS2] Extended a...
82
83
  		if (!(bh->b_data <= (char *)ea && (char *)GFS2_EA2NEXT(ea) <=
  						  bh->b_data + bh->b_size))
b3b94faa5   David Teigland   [GFS2] The core o...
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
  			goto fail;
  		if (!GFS2_EATYPE_VALID(ea->ea_type))
  			goto fail;
  
  		error = ea_call(ip, bh, ea, prev, data);
  		if (error)
  			return error;
  
  		if (GFS2_EA_IS_LAST(ea)) {
  			if ((char *)GFS2_EA2NEXT(ea) !=
  			    bh->b_data + bh->b_size)
  				goto fail;
  			break;
  		}
  	}
  
  	return error;
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
101
  fail:
b3b94faa5   David Teigland   [GFS2] The core o...
102
103
104
105
106
107
108
  	gfs2_consist_inode(ip);
  	return -EIO;
  }
  
  static int ea_foreach(struct gfs2_inode *ip, ea_call_t ea_call, void *data)
  {
  	struct buffer_head *bh, *eabh;
b44b84d76   Al Viro   [GFS2] gfs2 misc ...
109
  	__be64 *eablk, *end;
b3b94faa5   David Teigland   [GFS2] The core o...
110
  	int error;
3767ac21f   Steven Whitehouse   GFS2: Move di_eat...
111
  	error = gfs2_meta_read(ip->i_gl, ip->i_eattr, DIO_WAIT, &bh);
b3b94faa5   David Teigland   [GFS2] The core o...
112
113
  	if (error)
  		return error;
383f01fbf   Steven Whitehouse   GFS2: Banish stru...
114
  	if (!(ip->i_diskflags & GFS2_DIF_EA_INDIRECT)) {
b3b94faa5   David Teigland   [GFS2] The core o...
115
116
117
  		error = ea_foreach_i(ip, bh, ea_call, data);
  		goto out;
  	}
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
118
  	if (gfs2_metatype_check(GFS2_SB(&ip->i_inode), bh, GFS2_METATYPE_IN)) {
b3b94faa5   David Teigland   [GFS2] The core o...
119
120
121
  		error = -EIO;
  		goto out;
  	}
b44b84d76   Al Viro   [GFS2] gfs2 misc ...
122
  	eablk = (__be64 *)(bh->b_data + sizeof(struct gfs2_meta_header));
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
123
  	end = eablk + GFS2_SB(&ip->i_inode)->sd_inptrs;
b3b94faa5   David Teigland   [GFS2] The core o...
124
125
  
  	for (; eablk < end; eablk++) {
cd915493f   Steven Whitehouse   [GFS2] Change all...
126
  		u64 bn;
b3b94faa5   David Teigland   [GFS2] The core o...
127
128
129
130
  
  		if (!*eablk)
  			break;
  		bn = be64_to_cpu(*eablk);
7276b3b0c   Steven Whitehouse   [GFS2] Tidy up me...
131
  		error = gfs2_meta_read(ip->i_gl, bn, DIO_WAIT, &eabh);
b3b94faa5   David Teigland   [GFS2] The core o...
132
133
134
135
136
137
138
  		if (error)
  			break;
  		error = ea_foreach_i(ip, eabh, ea_call, data);
  		brelse(eabh);
  		if (error)
  			break;
  	}
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
139
  out:
b3b94faa5   David Teigland   [GFS2] The core o...
140
  	brelse(bh);
b3b94faa5   David Teigland   [GFS2] The core o...
141
142
143
144
  	return error;
  }
  
  struct ea_find {
40b78a322   Steven Whitehouse   GFS2: Clean up of...
145
146
147
  	int type;
  	const char *name;
  	size_t namel;
b3b94faa5   David Teigland   [GFS2] The core o...
148
149
150
151
152
153
154
155
  	struct gfs2_ea_location *ef_el;
  };
  
  static int ea_find_i(struct gfs2_inode *ip, struct buffer_head *bh,
  		     struct gfs2_ea_header *ea, struct gfs2_ea_header *prev,
  		     void *private)
  {
  	struct ea_find *ef = private;
b3b94faa5   David Teigland   [GFS2] The core o...
156
157
158
  
  	if (ea->ea_type == GFS2_EATYPE_UNUSED)
  		return 0;
40b78a322   Steven Whitehouse   GFS2: Clean up of...
159
160
161
  	if (ea->ea_type == ef->type) {
  		if (ea->ea_name_len == ef->namel &&
  		    !memcmp(GFS2_EA2NAME(ea), ef->name, ea->ea_name_len)) {
b3b94faa5   David Teigland   [GFS2] The core o...
162
163
164
165
166
167
168
169
  			struct gfs2_ea_location *el = ef->ef_el;
  			get_bh(bh);
  			el->el_bh = bh;
  			el->el_ea = ea;
  			el->el_prev = prev;
  			return 1;
  		}
  	}
b3b94faa5   David Teigland   [GFS2] The core o...
170
171
  	return 0;
  }
479c427dd   Steven Whitehouse   GFS2: Clean up ACLs
172
173
  static int gfs2_ea_find(struct gfs2_inode *ip, int type, const char *name,
  			struct gfs2_ea_location *el)
b3b94faa5   David Teigland   [GFS2] The core o...
174
175
176
  {
  	struct ea_find ef;
  	int error;
40b78a322   Steven Whitehouse   GFS2: Clean up of...
177
178
179
  	ef.type = type;
  	ef.name = name;
  	ef.namel = strlen(name);
b3b94faa5   David Teigland   [GFS2] The core o...
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
  	ef.ef_el = el;
  
  	memset(el, 0, sizeof(struct gfs2_ea_location));
  
  	error = ea_foreach(ip, ea_find_i, &ef);
  	if (error > 0)
  		return 0;
  
  	return error;
  }
  
  /**
   * ea_dealloc_unstuffed -
   * @ip:
   * @bh:
   * @ea:
   * @prev:
   * @private:
   *
   * Take advantage of the fact that all unstuffed blocks are
   * allocated from the same RG.  But watch, this may not always
   * be true.
   *
   * Returns: errno
   */
  
  static int ea_dealloc_unstuffed(struct gfs2_inode *ip, struct buffer_head *bh,
  				struct gfs2_ea_header *ea,
  				struct gfs2_ea_header *prev, void *private)
  {
  	int *leave = private;
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
211
  	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
b3b94faa5   David Teigland   [GFS2] The core o...
212
213
214
  	struct gfs2_rgrpd *rgd;
  	struct gfs2_holder rg_gh;
  	struct buffer_head *dibh;
b44b84d76   Al Viro   [GFS2] gfs2 misc ...
215
216
  	__be64 *dataptrs;
  	u64 bn = 0;
cd915493f   Steven Whitehouse   [GFS2] Change all...
217
  	u64 bstart = 0;
b3b94faa5   David Teigland   [GFS2] The core o...
218
219
220
221
222
223
224
225
226
  	unsigned int blen = 0;
  	unsigned int blks = 0;
  	unsigned int x;
  	int error;
  
  	if (GFS2_EA_IS_STUFFED(ea))
  		return 0;
  
  	dataptrs = GFS2_EA2DATAPTRS(ea);
cca195c5c   Steven Whitehouse   [GFS2] Extended a...
227
  	for (x = 0; x < ea->ea_num_ptrs; x++, dataptrs++) {
b3b94faa5   David Teigland   [GFS2] The core o...
228
229
230
231
  		if (*dataptrs) {
  			blks++;
  			bn = be64_to_cpu(*dataptrs);
  		}
cca195c5c   Steven Whitehouse   [GFS2] Extended a...
232
  	}
b3b94faa5   David Teigland   [GFS2] The core o...
233
234
235
236
237
238
239
240
241
242
243
244
  	if (!blks)
  		return 0;
  
  	rgd = gfs2_blk2rgrpd(sdp, bn);
  	if (!rgd) {
  		gfs2_consist_inode(ip);
  		return -EIO;
  	}
  
  	error = gfs2_glock_nq_init(rgd->rd_gl, LM_ST_EXCLUSIVE, 0, &rg_gh);
  	if (error)
  		return error;
bb8d8a6f5   Steven Whitehouse   [GFS2] Fix sign p...
245
  	error = gfs2_trans_begin(sdp, rgd->rd_length + RES_DINODE +
cca195c5c   Steven Whitehouse   [GFS2] Extended a...
246
  				 RES_EATTR + RES_STATFS + RES_QUOTA, blks);
b3b94faa5   David Teigland   [GFS2] The core o...
247
248
  	if (error)
  		goto out_gunlock;
d4e9c4c3b   Steven Whitehouse   [GFS2] Add an add...
249
  	gfs2_trans_add_bh(ip->i_gl, bh, 1);
b3b94faa5   David Teigland   [GFS2] The core o...
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
  
  	dataptrs = GFS2_EA2DATAPTRS(ea);
  	for (x = 0; x < ea->ea_num_ptrs; x++, dataptrs++) {
  		if (!*dataptrs)
  			break;
  		bn = be64_to_cpu(*dataptrs);
  
  		if (bstart + blen == bn)
  			blen++;
  		else {
  			if (bstart)
  				gfs2_free_meta(ip, bstart, blen);
  			bstart = bn;
  			blen = 1;
  		}
  
  		*dataptrs = 0;
77658aad2   Steven Whitehouse   [GFS2] Eliminate ...
267
  		gfs2_add_inode_blocks(&ip->i_inode, -1);
b3b94faa5   David Teigland   [GFS2] The core o...
268
269
270
271
272
  	}
  	if (bstart)
  		gfs2_free_meta(ip, bstart, blen);
  
  	if (prev && !leave) {
cd915493f   Steven Whitehouse   [GFS2] Change all...
273
  		u32 len;
b3b94faa5   David Teigland   [GFS2] The core o...
274
275
276
277
278
279
280
281
282
283
284
285
286
  
  		len = GFS2_EA_REC_LEN(prev) + GFS2_EA_REC_LEN(ea);
  		prev->ea_rec_len = cpu_to_be32(len);
  
  		if (GFS2_EA_IS_LAST(ea))
  			prev->ea_flags |= GFS2_EAFLAG_LAST;
  	} else {
  		ea->ea_type = GFS2_EATYPE_UNUSED;
  		ea->ea_num_ptrs = 0;
  	}
  
  	error = gfs2_meta_inode_buffer(ip, &dibh);
  	if (!error) {
4bd91ba18   Steven Whitehouse   [GFS2] Add nanose...
287
  		ip->i_inode.i_ctime = CURRENT_TIME;
d4e9c4c3b   Steven Whitehouse   [GFS2] Add an add...
288
  		gfs2_trans_add_bh(ip->i_gl, dibh, 1);
539e5d6b7   Steven Whitehouse   [GFS2] Change arg...
289
  		gfs2_dinode_out(ip, dibh->b_data);
b3b94faa5   David Teigland   [GFS2] The core o...
290
291
292
293
  		brelse(dibh);
  	}
  
  	gfs2_trans_end(sdp);
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
294
  out_gunlock:
b3b94faa5   David Teigland   [GFS2] The core o...
295
  	gfs2_glock_dq_uninit(&rg_gh);
b3b94faa5   David Teigland   [GFS2] The core o...
296
297
298
299
300
301
302
  	return error;
  }
  
  static int ea_remove_unstuffed(struct gfs2_inode *ip, struct buffer_head *bh,
  			       struct gfs2_ea_header *ea,
  			       struct gfs2_ea_header *prev, int leave)
  {
564e12b11   Bob Peterson   GFS2: decouple qu...
303
  	struct gfs2_qadata *qa;
b3b94faa5   David Teigland   [GFS2] The core o...
304
  	int error;
564e12b11   Bob Peterson   GFS2: decouple qu...
305
306
  	qa = gfs2_qadata_get(ip);
  	if (!qa)
182fe5abd   Cyrill Gorcunov   [GFS2] possible n...
307
  		return -ENOMEM;
b3b94faa5   David Teigland   [GFS2] The core o...
308
309
310
311
  
  	error = gfs2_quota_hold(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
  	if (error)
  		goto out_alloc;
cca195c5c   Steven Whitehouse   [GFS2] Extended a...
312
  	error = ea_dealloc_unstuffed(ip, bh, ea, prev, (leave) ? &error : NULL);
b3b94faa5   David Teigland   [GFS2] The core o...
313

b3b94faa5   David Teigland   [GFS2] The core o...
314
  	gfs2_quota_unhold(ip);
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
315
  out_alloc:
564e12b11   Bob Peterson   GFS2: decouple qu...
316
  	gfs2_qadata_put(ip);
b3b94faa5   David Teigland   [GFS2] The core o...
317
318
  	return error;
  }
b3b94faa5   David Teigland   [GFS2] The core o...
319
320
321
322
  struct ea_list {
  	struct gfs2_ea_request *ei_er;
  	unsigned int ei_size;
  };
40b78a322   Steven Whitehouse   GFS2: Clean up of...
323
324
325
326
327
328
329
330
331
332
333
334
335
  static inline unsigned int gfs2_ea_strlen(struct gfs2_ea_header *ea)
  {
  	switch (ea->ea_type) {
  	case GFS2_EATYPE_USR:
  		return 5 + ea->ea_name_len + 1;
  	case GFS2_EATYPE_SYS:
  		return 7 + ea->ea_name_len + 1;
  	case GFS2_EATYPE_SECURITY:
  		return 9 + ea->ea_name_len + 1;
  	default:
  		return 0;
  	}
  }
b3b94faa5   David Teigland   [GFS2] The core o...
336
337
338
339
340
341
  static int ea_list_i(struct gfs2_inode *ip, struct buffer_head *bh,
  		     struct gfs2_ea_header *ea, struct gfs2_ea_header *prev,
  		     void *private)
  {
  	struct ea_list *ei = private;
  	struct gfs2_ea_request *er = ei->ei_er;
639b6d79b   Ryan O'Hara   [GFS2] selinux su...
342
  	unsigned int ea_size = gfs2_ea_strlen(ea);
b3b94faa5   David Teigland   [GFS2] The core o...
343
344
345
346
347
  
  	if (ea->ea_type == GFS2_EATYPE_UNUSED)
  		return 0;
  
  	if (er->er_data_len) {
01eb7c079   Steven Whitehouse   [GFS2] Fix warnin...
348
349
  		char *prefix = NULL;
  		unsigned int l = 0;
b3b94faa5   David Teigland   [GFS2] The core o...
350
351
352
353
  		char c = 0;
  
  		if (ei->ei_size + ea_size > er->er_data_len)
  			return -ERANGE;
639b6d79b   Ryan O'Hara   [GFS2] selinux su...
354
355
  		switch (ea->ea_type) {
  		case GFS2_EATYPE_USR:
b3b94faa5   David Teigland   [GFS2] The core o...
356
357
  			prefix = "user.";
  			l = 5;
639b6d79b   Ryan O'Hara   [GFS2] selinux su...
358
359
  			break;
  		case GFS2_EATYPE_SYS:
b3b94faa5   David Teigland   [GFS2] The core o...
360
361
  			prefix = "system.";
  			l = 7;
639b6d79b   Ryan O'Hara   [GFS2] selinux su...
362
363
364
365
366
  			break;
  		case GFS2_EATYPE_SECURITY:
  			prefix = "security.";
  			l = 9;
  			break;
b3b94faa5   David Teigland   [GFS2] The core o...
367
  		}
01eb7c079   Steven Whitehouse   [GFS2] Fix warnin...
368
  		BUG_ON(l == 0);
90cdd2083   Steven Whitehouse   [GFS2] Flag up is...
369
370
  		memcpy(er->er_data + ei->ei_size, prefix, l);
  		memcpy(er->er_data + ei->ei_size + l, GFS2_EA2NAME(ea),
b3b94faa5   David Teigland   [GFS2] The core o...
371
  		       ea->ea_name_len);
90cdd2083   Steven Whitehouse   [GFS2] Flag up is...
372
  		memcpy(er->er_data + ei->ei_size + ea_size - 1, &c, 1);
b3b94faa5   David Teigland   [GFS2] The core o...
373
374
375
376
377
378
379
380
  	}
  
  	ei->ei_size += ea_size;
  
  	return 0;
  }
  
  /**
40b78a322   Steven Whitehouse   GFS2: Clean up of...
381
382
383
384
   * gfs2_listxattr - List gfs2 extended attributes
   * @dentry: The dentry whose inode we are interested in
   * @buffer: The buffer to write the results
   * @size: The size of the buffer
b3b94faa5   David Teigland   [GFS2] The core o...
385
386
387
   *
   * Returns: actual size of data on success, -errno on error
   */
40b78a322   Steven Whitehouse   GFS2: Clean up of...
388
  ssize_t gfs2_listxattr(struct dentry *dentry, char *buffer, size_t size)
b3b94faa5   David Teigland   [GFS2] The core o...
389
  {
40b78a322   Steven Whitehouse   GFS2: Clean up of...
390
391
  	struct gfs2_inode *ip = GFS2_I(dentry->d_inode);
  	struct gfs2_ea_request er;
b3b94faa5   David Teigland   [GFS2] The core o...
392
393
  	struct gfs2_holder i_gh;
  	int error;
40b78a322   Steven Whitehouse   GFS2: Clean up of...
394
395
396
397
  	memset(&er, 0, sizeof(struct gfs2_ea_request));
  	if (size) {
  		er.er_data = buffer;
  		er.er_data_len = size;
b3b94faa5   David Teigland   [GFS2] The core o...
398
  	}
cca195c5c   Steven Whitehouse   [GFS2] Extended a...
399
  	error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh);
b3b94faa5   David Teigland   [GFS2] The core o...
400
401
  	if (error)
  		return error;
3767ac21f   Steven Whitehouse   GFS2: Move di_eat...
402
  	if (ip->i_eattr) {
40b78a322   Steven Whitehouse   GFS2: Clean up of...
403
  		struct ea_list ei = { .ei_er = &er, .ei_size = 0 };
b3b94faa5   David Teigland   [GFS2] The core o...
404
405
406
407
408
409
410
411
412
413
414
415
416
417
  
  		error = ea_foreach(ip, ea_list_i, &ei);
  		if (!error)
  			error = ei.ei_size;
  	}
  
  	gfs2_glock_dq_uninit(&i_gh);
  
  	return error;
  }
  
  /**
   * ea_get_unstuffed - actually copies the unstuffed data into the
   *                    request buffer
cca195c5c   Steven Whitehouse   [GFS2] Extended a...
418
419
420
   * @ip: The GFS2 inode
   * @ea: The extended attribute header structure
   * @data: The data to be copied
b3b94faa5   David Teigland   [GFS2] The core o...
421
422
423
424
425
426
427
   *
   * Returns: errno
   */
  
  static int ea_get_unstuffed(struct gfs2_inode *ip, struct gfs2_ea_header *ea,
  			    char *data)
  {
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
428
  	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
b3b94faa5   David Teigland   [GFS2] The core o...
429
430
  	struct buffer_head **bh;
  	unsigned int amount = GFS2_EA_DATA_LEN(ea);
5c676f6d3   Steven Whitehouse   [GFS2] Macros rem...
431
  	unsigned int nptrs = DIV_ROUND_UP(amount, sdp->sd_jbsize);
b44b84d76   Al Viro   [GFS2] gfs2 misc ...
432
  	__be64 *dataptrs = GFS2_EA2DATAPTRS(ea);
b3b94faa5   David Teigland   [GFS2] The core o...
433
434
  	unsigned int x;
  	int error = 0;
16c5f06f1   Josef Bacik   [GFS2] fix GFP_KE...
435
  	bh = kcalloc(nptrs, sizeof(struct buffer_head *), GFP_NOFS);
b3b94faa5   David Teigland   [GFS2] The core o...
436
437
438
439
  	if (!bh)
  		return -ENOMEM;
  
  	for (x = 0; x < nptrs; x++) {
7276b3b0c   Steven Whitehouse   [GFS2] Tidy up me...
440
441
  		error = gfs2_meta_read(ip->i_gl, be64_to_cpu(*dataptrs), 0,
  				       bh + x);
b3b94faa5   David Teigland   [GFS2] The core o...
442
443
444
445
446
447
448
449
450
  		if (error) {
  			while (x--)
  				brelse(bh[x]);
  			goto out;
  		}
  		dataptrs++;
  	}
  
  	for (x = 0; x < nptrs; x++) {
7276b3b0c   Steven Whitehouse   [GFS2] Tidy up me...
451
  		error = gfs2_meta_wait(sdp, bh[x]);
b3b94faa5   David Teigland   [GFS2] The core o...
452
453
454
455
456
457
458
459
460
461
462
  		if (error) {
  			for (; x < nptrs; x++)
  				brelse(bh[x]);
  			goto out;
  		}
  		if (gfs2_metatype_check(sdp, bh[x], GFS2_METATYPE_ED)) {
  			for (; x < nptrs; x++)
  				brelse(bh[x]);
  			error = -EIO;
  			goto out;
  		}
cca195c5c   Steven Whitehouse   [GFS2] Extended a...
463
  		memcpy(data, bh[x]->b_data + sizeof(struct gfs2_meta_header),
b3b94faa5   David Teigland   [GFS2] The core o...
464
465
466
467
468
469
470
  		       (sdp->sd_jbsize > amount) ? amount : sdp->sd_jbsize);
  
  		amount -= sdp->sd_jbsize;
  		data += sdp->sd_jbsize;
  
  		brelse(bh[x]);
  	}
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
471
  out:
b3b94faa5   David Teigland   [GFS2] The core o...
472
  	kfree(bh);
b3b94faa5   David Teigland   [GFS2] The core o...
473
474
  	return error;
  }
479c427dd   Steven Whitehouse   GFS2: Clean up ACLs
475
476
  static int gfs2_ea_get_copy(struct gfs2_inode *ip, struct gfs2_ea_location *el,
  			    char *data, size_t size)
b3b94faa5   David Teigland   [GFS2] The core o...
477
  {
40b78a322   Steven Whitehouse   GFS2: Clean up of...
478
479
480
481
  	int ret;
  	size_t len = GFS2_EA_DATA_LEN(el->el_ea);
  	if (len > size)
  		return -ERANGE;
b3b94faa5   David Teigland   [GFS2] The core o...
482
  	if (GFS2_EA_IS_STUFFED(el->el_ea)) {
40b78a322   Steven Whitehouse   GFS2: Clean up of...
483
484
485
486
487
488
489
  		memcpy(data, GFS2_EA2DATA(el->el_ea), len);
  		return len;
  	}
  	ret = ea_get_unstuffed(ip, el->el_ea, data);
  	if (ret < 0)
  		return ret;
  	return len;
b3b94faa5   David Teigland   [GFS2] The core o...
490
  }
479c427dd   Steven Whitehouse   GFS2: Clean up ACLs
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
  int gfs2_xattr_acl_get(struct gfs2_inode *ip, const char *name, char **ppdata)
  {
  	struct gfs2_ea_location el;
  	int error;
  	int len;
  	char *data;
  
  	error = gfs2_ea_find(ip, GFS2_EATYPE_SYS, name, &el);
  	if (error)
  		return error;
  	if (!el.el_ea)
  		goto out;
  	if (!GFS2_EA_DATA_LEN(el.el_ea))
  		goto out;
  
  	len = GFS2_EA_DATA_LEN(el.el_ea);
  	data = kmalloc(len, GFP_NOFS);
  	error = -ENOMEM;
  	if (data == NULL)
  		goto out;
  
  	error = gfs2_ea_get_copy(ip, &el, data, len);
114b80ce2   Steven Whitehouse   GFS2: Fix very un...
513
514
515
516
  	if (error < 0)
  		kfree(data);
  	else
  		*ppdata = data;
479c427dd   Steven Whitehouse   GFS2: Clean up ACLs
517
518
519
520
  out:
  	brelse(el.el_bh);
  	return error;
  }
b3b94faa5   David Teigland   [GFS2] The core o...
521
  /**
40b78a322   Steven Whitehouse   GFS2: Clean up of...
522
523
   * gfs2_xattr_get - Get a GFS2 extended attribute
   * @inode: The inode
40b78a322   Steven Whitehouse   GFS2: Clean up of...
524
525
526
   * @name: The name of the extended attribute
   * @buffer: The buffer to write the result into
   * @size: The size of the buffer
431547b3c   Christoph Hellwig   sanitize xattr ha...
527
   * @type: The type of extended attribute
b3b94faa5   David Teigland   [GFS2] The core o...
528
529
530
   *
   * Returns: actual size of data on success, -errno on error
   */
431547b3c   Christoph Hellwig   sanitize xattr ha...
531
532
  static int gfs2_xattr_get(struct dentry *dentry, const char *name,
  		void *buffer, size_t size, int type)
b3b94faa5   David Teigland   [GFS2] The core o...
533
  {
431547b3c   Christoph Hellwig   sanitize xattr ha...
534
  	struct gfs2_inode *ip = GFS2_I(dentry->d_inode);
b3b94faa5   David Teigland   [GFS2] The core o...
535
536
  	struct gfs2_ea_location el;
  	int error;
3767ac21f   Steven Whitehouse   GFS2: Move di_eat...
537
  	if (!ip->i_eattr)
b3b94faa5   David Teigland   [GFS2] The core o...
538
  		return -ENODATA;
40b78a322   Steven Whitehouse   GFS2: Clean up of...
539
540
  	if (strlen(name) > GFS2_EA_MAX_NAME_LEN)
  		return -EINVAL;
b3b94faa5   David Teigland   [GFS2] The core o...
541

40b78a322   Steven Whitehouse   GFS2: Clean up of...
542
  	error = gfs2_ea_find(ip, type, name, &el);
b3b94faa5   David Teigland   [GFS2] The core o...
543
544
545
546
  	if (error)
  		return error;
  	if (!el.el_ea)
  		return -ENODATA;
86d006365   Steven Whitehouse   GFS2: Whitespace ...
547
  	if (size)
40b78a322   Steven Whitehouse   GFS2: Clean up of...
548
549
  		error = gfs2_ea_get_copy(ip, &el, buffer, size);
  	else
b3b94faa5   David Teigland   [GFS2] The core o...
550
  		error = GFS2_EA_DATA_LEN(el.el_ea);
b3b94faa5   David Teigland   [GFS2] The core o...
551
552
553
554
555
556
  	brelse(el.el_bh);
  
  	return error;
  }
  
  /**
b3b94faa5   David Teigland   [GFS2] The core o...
557
558
   * ea_alloc_blk - allocates a new block for extended attributes.
   * @ip: A pointer to the inode that's getting extended attributes
cca195c5c   Steven Whitehouse   [GFS2] Extended a...
559
   * @bhp: Pointer to pointer to a struct buffer_head
b3b94faa5   David Teigland   [GFS2] The core o...
560
561
562
563
564
565
   *
   * Returns: errno
   */
  
  static int ea_alloc_blk(struct gfs2_inode *ip, struct buffer_head **bhp)
  {
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
566
  	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
b3b94faa5   David Teigland   [GFS2] The core o...
567
  	struct gfs2_ea_header *ea;
b45e41d7d   Steven Whitehouse   [GFS2] Add extent...
568
  	unsigned int n = 1;
cd915493f   Steven Whitehouse   [GFS2] Change all...
569
  	u64 block;
090109783   Steven Whitehouse   GFS2: Improve res...
570
  	int error;
b3b94faa5   David Teigland   [GFS2] The core o...
571

6e87ed0fc   Bob Peterson   GFS2: move toward...
572
  	error = gfs2_alloc_blocks(ip, &block, &n, 0, NULL);
090109783   Steven Whitehouse   GFS2: Improve res...
573
574
  	if (error)
  		return error;
5731be53e   Steven Whitehouse   [GFS2] Update gfs...
575
  	gfs2_trans_add_unrevoke(sdp, block, 1);
b3b94faa5   David Teigland   [GFS2] The core o...
576
  	*bhp = gfs2_meta_new(ip->i_gl, block);
d4e9c4c3b   Steven Whitehouse   [GFS2] Add an add...
577
  	gfs2_trans_add_bh(ip->i_gl, *bhp, 1);
b3b94faa5   David Teigland   [GFS2] The core o...
578
579
580
581
582
583
584
585
  	gfs2_metatype_set(*bhp, GFS2_METATYPE_EA, GFS2_FORMAT_EA);
  	gfs2_buffer_clear_tail(*bhp, sizeof(struct gfs2_meta_header));
  
  	ea = GFS2_EA_BH2FIRST(*bhp);
  	ea->ea_rec_len = cpu_to_be32(sdp->sd_jbsize);
  	ea->ea_type = GFS2_EATYPE_UNUSED;
  	ea->ea_flags = GFS2_EAFLAG_LAST;
  	ea->ea_num_ptrs = 0;
77658aad2   Steven Whitehouse   [GFS2] Eliminate ...
586
  	gfs2_add_inode_blocks(&ip->i_inode, 1);
b3b94faa5   David Teigland   [GFS2] The core o...
587
588
589
590
591
592
593
  
  	return 0;
  }
  
  /**
   * ea_write - writes the request info to an ea, creating new blocks if
   *            necessary
cca195c5c   Steven Whitehouse   [GFS2] Extended a...
594
595
   * @ip: inode that is being modified
   * @ea: the location of the new ea in a block
b3b94faa5   David Teigland   [GFS2] The core o...
596
597
598
599
600
601
602
603
604
605
   * @er: the write request
   *
   * Note: does not update ea_rec_len or the GFS2_EAFLAG_LAST bin of ea_flags
   *
   * returns : errno
   */
  
  static int ea_write(struct gfs2_inode *ip, struct gfs2_ea_header *ea,
  		    struct gfs2_ea_request *er)
  {
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
606
  	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
090109783   Steven Whitehouse   GFS2: Improve res...
607
  	int error;
b3b94faa5   David Teigland   [GFS2] The core o...
608
609
610
611
612
613
614
615
616
617
618
619
  
  	ea->ea_data_len = cpu_to_be32(er->er_data_len);
  	ea->ea_name_len = er->er_name_len;
  	ea->ea_type = er->er_type;
  	ea->__pad = 0;
  
  	memcpy(GFS2_EA2NAME(ea), er->er_name, er->er_name_len);
  
  	if (GFS2_EAREQ_SIZE_STUFFED(er) <= sdp->sd_jbsize) {
  		ea->ea_num_ptrs = 0;
  		memcpy(GFS2_EA2DATA(ea), er->er_data, er->er_data_len);
  	} else {
b44b84d76   Al Viro   [GFS2] gfs2 misc ...
620
  		__be64 *dataptr = GFS2_EA2DATAPTRS(ea);
b3b94faa5   David Teigland   [GFS2] The core o...
621
622
623
624
  		const char *data = er->er_data;
  		unsigned int data_len = er->er_data_len;
  		unsigned int copy;
  		unsigned int x;
5c676f6d3   Steven Whitehouse   [GFS2] Macros rem...
625
  		ea->ea_num_ptrs = DIV_ROUND_UP(er->er_data_len, sdp->sd_jbsize);
b3b94faa5   David Teigland   [GFS2] The core o...
626
627
  		for (x = 0; x < ea->ea_num_ptrs; x++) {
  			struct buffer_head *bh;
cd915493f   Steven Whitehouse   [GFS2] Change all...
628
  			u64 block;
b3b94faa5   David Teigland   [GFS2] The core o...
629
  			int mh_size = sizeof(struct gfs2_meta_header);
b45e41d7d   Steven Whitehouse   [GFS2] Add extent...
630
  			unsigned int n = 1;
b3b94faa5   David Teigland   [GFS2] The core o...
631

6e87ed0fc   Bob Peterson   GFS2: move toward...
632
  			error = gfs2_alloc_blocks(ip, &block, &n, 0, NULL);
090109783   Steven Whitehouse   GFS2: Improve res...
633
634
  			if (error)
  				return error;
5731be53e   Steven Whitehouse   [GFS2] Update gfs...
635
  			gfs2_trans_add_unrevoke(sdp, block, 1);
b3b94faa5   David Teigland   [GFS2] The core o...
636
  			bh = gfs2_meta_new(ip->i_gl, block);
d4e9c4c3b   Steven Whitehouse   [GFS2] Add an add...
637
  			gfs2_trans_add_bh(ip->i_gl, bh, 1);
b3b94faa5   David Teigland   [GFS2] The core o...
638
  			gfs2_metatype_set(bh, GFS2_METATYPE_ED, GFS2_FORMAT_ED);
77658aad2   Steven Whitehouse   [GFS2] Eliminate ...
639
  			gfs2_add_inode_blocks(&ip->i_inode, 1);
b3b94faa5   David Teigland   [GFS2] The core o...
640

cca195c5c   Steven Whitehouse   [GFS2] Extended a...
641
642
  			copy = data_len > sdp->sd_jbsize ? sdp->sd_jbsize :
  							   data_len;
b3b94faa5   David Teigland   [GFS2] The core o...
643
644
645
646
  			memcpy(bh->b_data + mh_size, data, copy);
  			if (copy < sdp->sd_jbsize)
  				memset(bh->b_data + mh_size + copy, 0,
  				       sdp->sd_jbsize - copy);
cca195c5c   Steven Whitehouse   [GFS2] Extended a...
647
  			*dataptr++ = cpu_to_be64(bh->b_blocknr);
b3b94faa5   David Teigland   [GFS2] The core o...
648
649
650
651
652
653
654
655
656
657
658
659
660
  			data += copy;
  			data_len -= copy;
  
  			brelse(bh);
  		}
  
  		gfs2_assert_withdraw(sdp, !data_len);
  	}
  
  	return 0;
  }
  
  typedef int (*ea_skeleton_call_t) (struct gfs2_inode *ip,
cca195c5c   Steven Whitehouse   [GFS2] Extended a...
661
  				   struct gfs2_ea_request *er, void *private);
b3b94faa5   David Teigland   [GFS2] The core o...
662
663
664
  
  static int ea_alloc_skeleton(struct gfs2_inode *ip, struct gfs2_ea_request *er,
  			     unsigned int blks,
cca195c5c   Steven Whitehouse   [GFS2] Extended a...
665
  			     ea_skeleton_call_t skeleton_call, void *private)
b3b94faa5   David Teigland   [GFS2] The core o...
666
  {
564e12b11   Bob Peterson   GFS2: decouple qu...
667
  	struct gfs2_qadata *qa;
b3b94faa5   David Teigland   [GFS2] The core o...
668
669
  	struct buffer_head *dibh;
  	int error;
564e12b11   Bob Peterson   GFS2: decouple qu...
670
671
  	qa = gfs2_qadata_get(ip);
  	if (!qa)
182fe5abd   Cyrill Gorcunov   [GFS2] possible n...
672
  		return -ENOMEM;
b3b94faa5   David Teigland   [GFS2] The core o...
673

d82661d96   Steven Whitehouse   [GFS2] Streamline...
674
  	error = gfs2_quota_lock_check(ip);
b3b94faa5   David Teigland   [GFS2] The core o...
675
676
  	if (error)
  		goto out;
564e12b11   Bob Peterson   GFS2: decouple qu...
677
  	error = gfs2_inplace_reserve(ip, blks);
b3b94faa5   David Teigland   [GFS2] The core o...
678
679
  	if (error)
  		goto out_gunlock_q;
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
680
  	error = gfs2_trans_begin(GFS2_SB(&ip->i_inode),
54335b1fc   Steven Whitehouse   GFS2: Cache the m...
681
  				 blks + gfs2_rg_blocks(ip) +
b3b94faa5   David Teigland   [GFS2] The core o...
682
683
684
685
686
687
688
689
690
691
  				 RES_DINODE + RES_STATFS + RES_QUOTA, 0);
  	if (error)
  		goto out_ipres;
  
  	error = skeleton_call(ip, er, private);
  	if (error)
  		goto out_end_trans;
  
  	error = gfs2_meta_inode_buffer(ip, &dibh);
  	if (!error) {
4bd91ba18   Steven Whitehouse   [GFS2] Add nanose...
692
  		ip->i_inode.i_ctime = CURRENT_TIME;
d4e9c4c3b   Steven Whitehouse   [GFS2] Add an add...
693
  		gfs2_trans_add_bh(ip->i_gl, dibh, 1);
539e5d6b7   Steven Whitehouse   [GFS2] Change arg...
694
  		gfs2_dinode_out(ip, dibh->b_data);
b3b94faa5   David Teigland   [GFS2] The core o...
695
696
  		brelse(dibh);
  	}
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
697
  out_end_trans:
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
698
  	gfs2_trans_end(GFS2_SB(&ip->i_inode));
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
699
  out_ipres:
b3b94faa5   David Teigland   [GFS2] The core o...
700
  	gfs2_inplace_release(ip);
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
701
  out_gunlock_q:
b3b94faa5   David Teigland   [GFS2] The core o...
702
  	gfs2_quota_unlock(ip);
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
703
  out:
564e12b11   Bob Peterson   GFS2: decouple qu...
704
  	gfs2_qadata_put(ip);
b3b94faa5   David Teigland   [GFS2] The core o...
705
706
707
708
709
710
711
712
713
714
715
716
  	return error;
  }
  
  static int ea_init_i(struct gfs2_inode *ip, struct gfs2_ea_request *er,
  		     void *private)
  {
  	struct buffer_head *bh;
  	int error;
  
  	error = ea_alloc_blk(ip, &bh);
  	if (error)
  		return error;
3767ac21f   Steven Whitehouse   GFS2: Move di_eat...
717
  	ip->i_eattr = bh->b_blocknr;
b3b94faa5   David Teigland   [GFS2] The core o...
718
719
720
721
722
723
724
725
726
727
728
729
730
731
  	error = ea_write(ip, GFS2_EA_BH2FIRST(bh), er);
  
  	brelse(bh);
  
  	return error;
  }
  
  /**
   * ea_init - initializes a new eattr block
   * @ip:
   * @er:
   *
   * Returns: errno
   */
40b78a322   Steven Whitehouse   GFS2: Clean up of...
732
733
  static int ea_init(struct gfs2_inode *ip, int type, const char *name,
  		   const void *data, size_t size)
b3b94faa5   David Teigland   [GFS2] The core o...
734
  {
40b78a322   Steven Whitehouse   GFS2: Clean up of...
735
  	struct gfs2_ea_request er;
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
736
  	unsigned int jbsize = GFS2_SB(&ip->i_inode)->sd_jbsize;
b3b94faa5   David Teigland   [GFS2] The core o...
737
  	unsigned int blks = 1;
40b78a322   Steven Whitehouse   GFS2: Clean up of...
738
739
740
741
742
743
744
745
  	er.er_type = type;
  	er.er_name = name;
  	er.er_name_len = strlen(name);
  	er.er_data = (void *)data;
  	er.er_data_len = size;
  
  	if (GFS2_EAREQ_SIZE_STUFFED(&er) > jbsize)
  		blks += DIV_ROUND_UP(er.er_data_len, jbsize);
b3b94faa5   David Teigland   [GFS2] The core o...
746

40b78a322   Steven Whitehouse   GFS2: Clean up of...
747
  	return ea_alloc_skeleton(ip, &er, blks, ea_init_i, NULL);
b3b94faa5   David Teigland   [GFS2] The core o...
748
749
750
751
  }
  
  static struct gfs2_ea_header *ea_split_ea(struct gfs2_ea_header *ea)
  {
cd915493f   Steven Whitehouse   [GFS2] Change all...
752
  	u32 ea_size = GFS2_EA_SIZE(ea);
568f4c965   Steven Whitehouse   [GFS2] 80 Column ...
753
754
  	struct gfs2_ea_header *new = (struct gfs2_ea_header *)((char *)ea +
  				     ea_size);
cd915493f   Steven Whitehouse   [GFS2] Change all...
755
  	u32 new_size = GFS2_EA_REC_LEN(ea) - ea_size;
b3b94faa5   David Teigland   [GFS2] The core o...
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
  	int last = ea->ea_flags & GFS2_EAFLAG_LAST;
  
  	ea->ea_rec_len = cpu_to_be32(ea_size);
  	ea->ea_flags ^= last;
  
  	new->ea_rec_len = cpu_to_be32(new_size);
  	new->ea_flags = last;
  
  	return new;
  }
  
  static void ea_set_remove_stuffed(struct gfs2_inode *ip,
  				  struct gfs2_ea_location *el)
  {
  	struct gfs2_ea_header *ea = el->el_ea;
  	struct gfs2_ea_header *prev = el->el_prev;
cd915493f   Steven Whitehouse   [GFS2] Change all...
772
  	u32 len;
b3b94faa5   David Teigland   [GFS2] The core o...
773

d4e9c4c3b   Steven Whitehouse   [GFS2] Add an add...
774
  	gfs2_trans_add_bh(ip->i_gl, el->el_bh, 1);
b3b94faa5   David Teigland   [GFS2] The core o...
775
776
777
778
779
780
  
  	if (!prev || !GFS2_EA_IS_STUFFED(ea)) {
  		ea->ea_type = GFS2_EATYPE_UNUSED;
  		return;
  	} else if (GFS2_EA2NEXT(prev) != ea) {
  		prev = GFS2_EA2NEXT(prev);
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
781
  		gfs2_assert_withdraw(GFS2_SB(&ip->i_inode), GFS2_EA2NEXT(prev) == ea);
b3b94faa5   David Teigland   [GFS2] The core o...
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
  	}
  
  	len = GFS2_EA_REC_LEN(prev) + GFS2_EA_REC_LEN(ea);
  	prev->ea_rec_len = cpu_to_be32(len);
  
  	if (GFS2_EA_IS_LAST(ea))
  		prev->ea_flags |= GFS2_EAFLAG_LAST;
  }
  
  struct ea_set {
  	int ea_split;
  
  	struct gfs2_ea_request *es_er;
  	struct gfs2_ea_location *es_el;
  
  	struct buffer_head *es_bh;
  	struct gfs2_ea_header *es_ea;
  };
  
  static int ea_set_simple_noalloc(struct gfs2_inode *ip, struct buffer_head *bh,
  				 struct gfs2_ea_header *ea, struct ea_set *es)
  {
  	struct gfs2_ea_request *er = es->es_er;
  	struct buffer_head *dibh;
  	int error;
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
807
  	error = gfs2_trans_begin(GFS2_SB(&ip->i_inode), RES_DINODE + 2 * RES_EATTR, 0);
b3b94faa5   David Teigland   [GFS2] The core o...
808
809
  	if (error)
  		return error;
d4e9c4c3b   Steven Whitehouse   [GFS2] Add an add...
810
  	gfs2_trans_add_bh(ip->i_gl, bh, 1);
b3b94faa5   David Teigland   [GFS2] The core o...
811
812
813
814
815
816
817
818
819
820
821
822
  
  	if (es->ea_split)
  		ea = ea_split_ea(ea);
  
  	ea_write(ip, ea, er);
  
  	if (es->es_el)
  		ea_set_remove_stuffed(ip, es->es_el);
  
  	error = gfs2_meta_inode_buffer(ip, &dibh);
  	if (error)
  		goto out;
4bd91ba18   Steven Whitehouse   [GFS2] Add nanose...
823
  	ip->i_inode.i_ctime = CURRENT_TIME;
d4e9c4c3b   Steven Whitehouse   [GFS2] Add an add...
824
  	gfs2_trans_add_bh(ip->i_gl, dibh, 1);
539e5d6b7   Steven Whitehouse   [GFS2] Change arg...
825
  	gfs2_dinode_out(ip, dibh->b_data);
b3b94faa5   David Teigland   [GFS2] The core o...
826
  	brelse(dibh);
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
827
  out:
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
828
  	gfs2_trans_end(GFS2_SB(&ip->i_inode));
b3b94faa5   David Teigland   [GFS2] The core o...
829
830
831
832
833
834
835
836
837
  	return error;
  }
  
  static int ea_set_simple_alloc(struct gfs2_inode *ip,
  			       struct gfs2_ea_request *er, void *private)
  {
  	struct ea_set *es = private;
  	struct gfs2_ea_header *ea = es->es_ea;
  	int error;
d4e9c4c3b   Steven Whitehouse   [GFS2] Add an add...
838
  	gfs2_trans_add_bh(ip->i_gl, es->es_bh, 1);
b3b94faa5   David Teigland   [GFS2] The core o...
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
  
  	if (es->ea_split)
  		ea = ea_split_ea(ea);
  
  	error = ea_write(ip, ea, er);
  	if (error)
  		return error;
  
  	if (es->es_el)
  		ea_set_remove_stuffed(ip, es->es_el);
  
  	return 0;
  }
  
  static int ea_set_simple(struct gfs2_inode *ip, struct buffer_head *bh,
  			 struct gfs2_ea_header *ea, struct gfs2_ea_header *prev,
  			 void *private)
  {
  	struct ea_set *es = private;
  	unsigned int size;
  	int stuffed;
  	int error;
40b78a322   Steven Whitehouse   GFS2: Clean up of...
861
862
  	stuffed = ea_calc_size(GFS2_SB(&ip->i_inode), es->es_er->er_name_len,
  			       es->es_er->er_data_len, &size);
b3b94faa5   David Teigland   [GFS2] The core o...
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
  
  	if (ea->ea_type == GFS2_EATYPE_UNUSED) {
  		if (GFS2_EA_REC_LEN(ea) < size)
  			return 0;
  		if (!GFS2_EA_IS_STUFFED(ea)) {
  			error = ea_remove_unstuffed(ip, bh, ea, prev, 1);
  			if (error)
  				return error;
  		}
  		es->ea_split = 0;
  	} else if (GFS2_EA_REC_LEN(ea) - GFS2_EA_SIZE(ea) >= size)
  		es->ea_split = 1;
  	else
  		return 0;
  
  	if (stuffed) {
  		error = ea_set_simple_noalloc(ip, bh, ea, es);
  		if (error)
  			return error;
  	} else {
  		unsigned int blks;
  
  		es->es_bh = bh;
  		es->es_ea = ea;
5c676f6d3   Steven Whitehouse   [GFS2] Macros rem...
887
  		blks = 2 + DIV_ROUND_UP(es->es_er->er_data_len,
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
888
  					GFS2_SB(&ip->i_inode)->sd_jbsize);
b3b94faa5   David Teigland   [GFS2] The core o...
889
890
891
892
893
894
895
896
897
898
899
900
901
  
  		error = ea_alloc_skeleton(ip, es->es_er, blks,
  					  ea_set_simple_alloc, es);
  		if (error)
  			return error;
  	}
  
  	return 1;
  }
  
  static int ea_set_block(struct gfs2_inode *ip, struct gfs2_ea_request *er,
  			void *private)
  {
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
902
  	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
b3b94faa5   David Teigland   [GFS2] The core o...
903
  	struct buffer_head *indbh, *newbh;
b44b84d76   Al Viro   [GFS2] gfs2 misc ...
904
  	__be64 *eablk;
b3b94faa5   David Teigland   [GFS2] The core o...
905
906
  	int error;
  	int mh_size = sizeof(struct gfs2_meta_header);
383f01fbf   Steven Whitehouse   GFS2: Banish stru...
907
  	if (ip->i_diskflags & GFS2_DIF_EA_INDIRECT) {
b44b84d76   Al Viro   [GFS2] gfs2 misc ...
908
  		__be64 *end;
b3b94faa5   David Teigland   [GFS2] The core o...
909

3767ac21f   Steven Whitehouse   GFS2: Move di_eat...
910
  		error = gfs2_meta_read(ip->i_gl, ip->i_eattr, DIO_WAIT,
7276b3b0c   Steven Whitehouse   [GFS2] Tidy up me...
911
  				       &indbh);
b3b94faa5   David Teigland   [GFS2] The core o...
912
913
914
915
916
917
918
  		if (error)
  			return error;
  
  		if (gfs2_metatype_check(sdp, indbh, GFS2_METATYPE_IN)) {
  			error = -EIO;
  			goto out;
  		}
b44b84d76   Al Viro   [GFS2] gfs2 misc ...
919
  		eablk = (__be64 *)(indbh->b_data + mh_size);
b3b94faa5   David Teigland   [GFS2] The core o...
920
921
922
923
924
925
926
927
928
929
  		end = eablk + sdp->sd_inptrs;
  
  		for (; eablk < end; eablk++)
  			if (!*eablk)
  				break;
  
  		if (eablk == end) {
  			error = -ENOSPC;
  			goto out;
  		}
d4e9c4c3b   Steven Whitehouse   [GFS2] Add an add...
930
  		gfs2_trans_add_bh(ip->i_gl, indbh, 1);
b3b94faa5   David Teigland   [GFS2] The core o...
931
  	} else {
cd915493f   Steven Whitehouse   [GFS2] Change all...
932
  		u64 blk;
b45e41d7d   Steven Whitehouse   [GFS2] Add extent...
933
  		unsigned int n = 1;
6e87ed0fc   Bob Peterson   GFS2: move toward...
934
  		error = gfs2_alloc_blocks(ip, &blk, &n, 0, NULL);
090109783   Steven Whitehouse   GFS2: Improve res...
935
936
  		if (error)
  			return error;
5731be53e   Steven Whitehouse   [GFS2] Update gfs...
937
  		gfs2_trans_add_unrevoke(sdp, blk, 1);
b3b94faa5   David Teigland   [GFS2] The core o...
938
  		indbh = gfs2_meta_new(ip->i_gl, blk);
d4e9c4c3b   Steven Whitehouse   [GFS2] Add an add...
939
  		gfs2_trans_add_bh(ip->i_gl, indbh, 1);
b3b94faa5   David Teigland   [GFS2] The core o...
940
941
  		gfs2_metatype_set(indbh, GFS2_METATYPE_IN, GFS2_FORMAT_IN);
  		gfs2_buffer_clear_tail(indbh, mh_size);
b44b84d76   Al Viro   [GFS2] gfs2 misc ...
942
  		eablk = (__be64 *)(indbh->b_data + mh_size);
3767ac21f   Steven Whitehouse   GFS2: Move di_eat...
943
944
  		*eablk = cpu_to_be64(ip->i_eattr);
  		ip->i_eattr = blk;
383f01fbf   Steven Whitehouse   GFS2: Banish stru...
945
  		ip->i_diskflags |= GFS2_DIF_EA_INDIRECT;
77658aad2   Steven Whitehouse   [GFS2] Eliminate ...
946
  		gfs2_add_inode_blocks(&ip->i_inode, 1);
b3b94faa5   David Teigland   [GFS2] The core o...
947
948
949
950
951
952
953
  
  		eablk++;
  	}
  
  	error = ea_alloc_blk(ip, &newbh);
  	if (error)
  		goto out;
cd915493f   Steven Whitehouse   [GFS2] Change all...
954
  	*eablk = cpu_to_be64((u64)newbh->b_blocknr);
b3b94faa5   David Teigland   [GFS2] The core o...
955
956
957
958
959
960
  	error = ea_write(ip, GFS2_EA_BH2FIRST(newbh), er);
  	brelse(newbh);
  	if (error)
  		goto out;
  
  	if (private)
cca195c5c   Steven Whitehouse   [GFS2] Extended a...
961
  		ea_set_remove_stuffed(ip, private);
b3b94faa5   David Teigland   [GFS2] The core o...
962

a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
963
  out:
b3b94faa5   David Teigland   [GFS2] The core o...
964
  	brelse(indbh);
b3b94faa5   David Teigland   [GFS2] The core o...
965
966
  	return error;
  }
40b78a322   Steven Whitehouse   GFS2: Clean up of...
967
968
  static int ea_set_i(struct gfs2_inode *ip, int type, const char *name,
  		    const void *value, size_t size, struct gfs2_ea_location *el)
b3b94faa5   David Teigland   [GFS2] The core o...
969
  {
40b78a322   Steven Whitehouse   GFS2: Clean up of...
970
  	struct gfs2_ea_request er;
b3b94faa5   David Teigland   [GFS2] The core o...
971
972
973
  	struct ea_set es;
  	unsigned int blks = 2;
  	int error;
40b78a322   Steven Whitehouse   GFS2: Clean up of...
974
975
976
977
978
  	er.er_type = type;
  	er.er_name = name;
  	er.er_data = (void *)value;
  	er.er_name_len = strlen(name);
  	er.er_data_len = size;
b3b94faa5   David Teigland   [GFS2] The core o...
979
  	memset(&es, 0, sizeof(struct ea_set));
40b78a322   Steven Whitehouse   GFS2: Clean up of...
980
  	es.es_er = &er;
b3b94faa5   David Teigland   [GFS2] The core o...
981
982
983
984
985
986
987
  	es.es_el = el;
  
  	error = ea_foreach(ip, ea_set_simple, &es);
  	if (error > 0)
  		return 0;
  	if (error)
  		return error;
383f01fbf   Steven Whitehouse   GFS2: Banish stru...
988
  	if (!(ip->i_diskflags & GFS2_DIF_EA_INDIRECT))
b3b94faa5   David Teigland   [GFS2] The core o...
989
  		blks++;
40b78a322   Steven Whitehouse   GFS2: Clean up of...
990
991
  	if (GFS2_EAREQ_SIZE_STUFFED(&er) > GFS2_SB(&ip->i_inode)->sd_jbsize)
  		blks += DIV_ROUND_UP(er.er_data_len, GFS2_SB(&ip->i_inode)->sd_jbsize);
b3b94faa5   David Teigland   [GFS2] The core o...
992

40b78a322   Steven Whitehouse   GFS2: Clean up of...
993
  	return ea_alloc_skeleton(ip, &er, blks, ea_set_block, el);
b3b94faa5   David Teigland   [GFS2] The core o...
994
995
996
997
998
999
1000
  }
  
  static int ea_set_remove_unstuffed(struct gfs2_inode *ip,
  				   struct gfs2_ea_location *el)
  {
  	if (el->el_prev && GFS2_EA2NEXT(el->el_prev) != el->el_ea) {
  		el->el_prev = GFS2_EA2NEXT(el->el_prev);
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
1001
  		gfs2_assert_withdraw(GFS2_SB(&ip->i_inode),
b3b94faa5   David Teigland   [GFS2] The core o...
1002
1003
  				     GFS2_EA2NEXT(el->el_prev) == el->el_ea);
  	}
86d006365   Steven Whitehouse   GFS2: Whitespace ...
1004
  	return ea_remove_unstuffed(ip, el->el_bh, el->el_ea, el->el_prev, 0);
b3b94faa5   David Teigland   [GFS2] The core o...
1005
  }
b3b94faa5   David Teigland   [GFS2] The core o...
1006
1007
1008
1009
1010
1011
  static int ea_remove_stuffed(struct gfs2_inode *ip, struct gfs2_ea_location *el)
  {
  	struct gfs2_ea_header *ea = el->el_ea;
  	struct gfs2_ea_header *prev = el->el_prev;
  	struct buffer_head *dibh;
  	int error;
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
1012
  	error = gfs2_trans_begin(GFS2_SB(&ip->i_inode), RES_DINODE + RES_EATTR, 0);
b3b94faa5   David Teigland   [GFS2] The core o...
1013
1014
  	if (error)
  		return error;
d4e9c4c3b   Steven Whitehouse   [GFS2] Add an add...
1015
  	gfs2_trans_add_bh(ip->i_gl, el->el_bh, 1);
b3b94faa5   David Teigland   [GFS2] The core o...
1016
1017
  
  	if (prev) {
cd915493f   Steven Whitehouse   [GFS2] Change all...
1018
  		u32 len;
b3b94faa5   David Teigland   [GFS2] The core o...
1019
1020
1021
1022
1023
1024
  
  		len = GFS2_EA_REC_LEN(prev) + GFS2_EA_REC_LEN(ea);
  		prev->ea_rec_len = cpu_to_be32(len);
  
  		if (GFS2_EA_IS_LAST(ea))
  			prev->ea_flags |= GFS2_EAFLAG_LAST;
40b78a322   Steven Whitehouse   GFS2: Clean up of...
1025
  	} else {
b3b94faa5   David Teigland   [GFS2] The core o...
1026
  		ea->ea_type = GFS2_EATYPE_UNUSED;
40b78a322   Steven Whitehouse   GFS2: Clean up of...
1027
  	}
b3b94faa5   David Teigland   [GFS2] The core o...
1028
1029
1030
  
  	error = gfs2_meta_inode_buffer(ip, &dibh);
  	if (!error) {
4bd91ba18   Steven Whitehouse   [GFS2] Add nanose...
1031
  		ip->i_inode.i_ctime = CURRENT_TIME;
d4e9c4c3b   Steven Whitehouse   [GFS2] Add an add...
1032
  		gfs2_trans_add_bh(ip->i_gl, dibh, 1);
539e5d6b7   Steven Whitehouse   [GFS2] Change arg...
1033
  		gfs2_dinode_out(ip, dibh->b_data);
b3b94faa5   David Teigland   [GFS2] The core o...
1034
  		brelse(dibh);
907b9bceb   Steven Whitehouse   [GFS2/DLM] Fix tr...
1035
  	}
b3b94faa5   David Teigland   [GFS2] The core o...
1036

feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
1037
  	gfs2_trans_end(GFS2_SB(&ip->i_inode));
b3b94faa5   David Teigland   [GFS2] The core o...
1038
1039
1040
  
  	return error;
  }
40b78a322   Steven Whitehouse   GFS2: Clean up of...
1041
1042
  /**
   * gfs2_xattr_remove - Remove a GFS2 extended attribute
431547b3c   Christoph Hellwig   sanitize xattr ha...
1043
   * @ip: The inode
40b78a322   Steven Whitehouse   GFS2: Clean up of...
1044
1045
1046
1047
1048
1049
1050
1051
1052
   * @type: The type of the extended attribute
   * @name: The name of the extended attribute
   *
   * This is not called directly by the VFS since we use the (common)
   * scheme of making a "set with NULL data" mean a remove request. Note
   * that this is different from a set with zero length data.
   *
   * Returns: 0, or errno on failure
   */
431547b3c   Christoph Hellwig   sanitize xattr ha...
1053
  static int gfs2_xattr_remove(struct gfs2_inode *ip, int type, const char *name)
b3b94faa5   David Teigland   [GFS2] The core o...
1054
1055
1056
  {
  	struct gfs2_ea_location el;
  	int error;
3767ac21f   Steven Whitehouse   GFS2: Move di_eat...
1057
  	if (!ip->i_eattr)
b3b94faa5   David Teigland   [GFS2] The core o...
1058
  		return -ENODATA;
40b78a322   Steven Whitehouse   GFS2: Clean up of...
1059
  	error = gfs2_ea_find(ip, type, name, &el);
b3b94faa5   David Teigland   [GFS2] The core o...
1060
1061
1062
1063
1064
1065
1066
1067
  	if (error)
  		return error;
  	if (!el.el_ea)
  		return -ENODATA;
  
  	if (GFS2_EA_IS_STUFFED(el.el_ea))
  		error = ea_remove_stuffed(ip, &el);
  	else
40b78a322   Steven Whitehouse   GFS2: Clean up of...
1068
  		error = ea_remove_unstuffed(ip, el.el_bh, el.el_ea, el.el_prev, 0);
b3b94faa5   David Teigland   [GFS2] The core o...
1069
1070
1071
1072
1073
1074
1075
  
  	brelse(el.el_bh);
  
  	return error;
  }
  
  /**
431547b3c   Christoph Hellwig   sanitize xattr ha...
1076
1077
   * __gfs2_xattr_set - Set (or remove) a GFS2 extended attribute
   * @ip: The inode
40b78a322   Steven Whitehouse   GFS2: Clean up of...
1078
1079
1080
1081
   * @name: The name of the extended attribute
   * @value: The value of the extended attribute (NULL for remove)
   * @size: The size of the @value argument
   * @flags: Create or Replace
431547b3c   Christoph Hellwig   sanitize xattr ha...
1082
   * @type: The type of the extended attribute
b3b94faa5   David Teigland   [GFS2] The core o...
1083
   *
40b78a322   Steven Whitehouse   GFS2: Clean up of...
1084
1085
1086
   * See gfs2_xattr_remove() for details of the removal of xattrs.
   *
   * Returns: 0 or errno on failure
b3b94faa5   David Teigland   [GFS2] The core o...
1087
   */
431547b3c   Christoph Hellwig   sanitize xattr ha...
1088
1089
  int __gfs2_xattr_set(struct inode *inode, const char *name,
  		   const void *value, size_t size, int flags, int type)
b3b94faa5   David Teigland   [GFS2] The core o...
1090
  {
40b78a322   Steven Whitehouse   GFS2: Clean up of...
1091
  	struct gfs2_inode *ip = GFS2_I(inode);
431547b3c   Christoph Hellwig   sanitize xattr ha...
1092
  	struct gfs2_sbd *sdp = GFS2_SB(inode);
40b78a322   Steven Whitehouse   GFS2: Clean up of...
1093
1094
  	struct gfs2_ea_location el;
  	unsigned int namel = strlen(name);
b3b94faa5   David Teigland   [GFS2] The core o...
1095
  	int error;
40b78a322   Steven Whitehouse   GFS2: Clean up of...
1096
1097
1098
1099
  	if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
  		return -EPERM;
  	if (namel > GFS2_EA_MAX_NAME_LEN)
  		return -ERANGE;
b3b94faa5   David Teigland   [GFS2] The core o...
1100

40b78a322   Steven Whitehouse   GFS2: Clean up of...
1101
  	if (value == NULL)
431547b3c   Christoph Hellwig   sanitize xattr ha...
1102
  		return gfs2_xattr_remove(ip, type, name);
40b78a322   Steven Whitehouse   GFS2: Clean up of...
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
  
  	if (ea_check_size(sdp, namel, size))
  		return -ERANGE;
  
  	if (!ip->i_eattr) {
  		if (flags & XATTR_REPLACE)
  			return -ENODATA;
  		return ea_init(ip, type, name, value, size);
  	}
  
  	error = gfs2_ea_find(ip, type, name, &el);
b3b94faa5   David Teigland   [GFS2] The core o...
1114
1115
  	if (error)
  		return error;
40b78a322   Steven Whitehouse   GFS2: Clean up of...
1116
1117
1118
1119
1120
  	if (el.el_ea) {
  		if (ip->i_diskflags & GFS2_DIF_APPENDONLY) {
  			brelse(el.el_bh);
  			return -EPERM;
  		}
b3b94faa5   David Teigland   [GFS2] The core o...
1121

40b78a322   Steven Whitehouse   GFS2: Clean up of...
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
  		error = -EEXIST;
  		if (!(flags & XATTR_CREATE)) {
  			int unstuffed = !GFS2_EA_IS_STUFFED(el.el_ea);
  			error = ea_set_i(ip, type, name, value, size, &el);
  			if (!error && unstuffed)
  				ea_set_remove_unstuffed(ip, &el);
  		}
  
  		brelse(el.el_bh);
  		return error;
  	}
  
  	error = -ENODATA;
  	if (!(flags & XATTR_REPLACE))
  		error = ea_set_i(ip, type, name, value, size, NULL);
b3b94faa5   David Teigland   [GFS2] The core o...
1137
1138
1139
  
  	return error;
  }
431547b3c   Christoph Hellwig   sanitize xattr ha...
1140
1141
1142
1143
1144
1145
  static int gfs2_xattr_set(struct dentry *dentry, const char *name,
  		const void *value, size_t size, int flags, int type)
  {
  	return __gfs2_xattr_set(dentry->d_inode, name, value,
  				size, flags, type);
  }
b3b94faa5   David Teigland   [GFS2] The core o...
1146
1147
1148
  static int ea_acl_chmod_unstuffed(struct gfs2_inode *ip,
  				  struct gfs2_ea_header *ea, char *data)
  {
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
1149
  	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
b3b94faa5   David Teigland   [GFS2] The core o...
1150
1151
  	struct buffer_head **bh;
  	unsigned int amount = GFS2_EA_DATA_LEN(ea);
5c676f6d3   Steven Whitehouse   [GFS2] Macros rem...
1152
  	unsigned int nptrs = DIV_ROUND_UP(amount, sdp->sd_jbsize);
b44b84d76   Al Viro   [GFS2] gfs2 misc ...
1153
  	__be64 *dataptrs = GFS2_EA2DATAPTRS(ea);
b3b94faa5   David Teigland   [GFS2] The core o...
1154
1155
  	unsigned int x;
  	int error;
16c5f06f1   Josef Bacik   [GFS2] fix GFP_KE...
1156
  	bh = kcalloc(nptrs, sizeof(struct buffer_head *), GFP_NOFS);
b3b94faa5   David Teigland   [GFS2] The core o...
1157
1158
1159
1160
1161
1162
1163
1164
  	if (!bh)
  		return -ENOMEM;
  
  	error = gfs2_trans_begin(sdp, nptrs + RES_DINODE, 0);
  	if (error)
  		goto out;
  
  	for (x = 0; x < nptrs; x++) {
7276b3b0c   Steven Whitehouse   [GFS2] Tidy up me...
1165
1166
  		error = gfs2_meta_read(ip->i_gl, be64_to_cpu(*dataptrs), 0,
  				       bh + x);
b3b94faa5   David Teigland   [GFS2] The core o...
1167
1168
1169
1170
1171
1172
1173
1174
1175
  		if (error) {
  			while (x--)
  				brelse(bh[x]);
  			goto fail;
  		}
  		dataptrs++;
  	}
  
  	for (x = 0; x < nptrs; x++) {
7276b3b0c   Steven Whitehouse   [GFS2] Tidy up me...
1176
  		error = gfs2_meta_wait(sdp, bh[x]);
b3b94faa5   David Teigland   [GFS2] The core o...
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
  		if (error) {
  			for (; x < nptrs; x++)
  				brelse(bh[x]);
  			goto fail;
  		}
  		if (gfs2_metatype_check(sdp, bh[x], GFS2_METATYPE_ED)) {
  			for (; x < nptrs; x++)
  				brelse(bh[x]);
  			error = -EIO;
  			goto fail;
  		}
d4e9c4c3b   Steven Whitehouse   [GFS2] Add an add...
1188
  		gfs2_trans_add_bh(ip->i_gl, bh[x], 1);
b3b94faa5   David Teigland   [GFS2] The core o...
1189

cca195c5c   Steven Whitehouse   [GFS2] Extended a...
1190
  		memcpy(bh[x]->b_data + sizeof(struct gfs2_meta_header), data,
b3b94faa5   David Teigland   [GFS2] The core o...
1191
1192
1193
1194
1195
1196
1197
  		       (sdp->sd_jbsize > amount) ? amount : sdp->sd_jbsize);
  
  		amount -= sdp->sd_jbsize;
  		data += sdp->sd_jbsize;
  
  		brelse(bh[x]);
  	}
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
1198
  out:
b3b94faa5   David Teigland   [GFS2] The core o...
1199
  	kfree(bh);
b3b94faa5   David Teigland   [GFS2] The core o...
1200
  	return error;
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
1201
  fail:
b3b94faa5   David Teigland   [GFS2] The core o...
1202
1203
  	gfs2_trans_end(sdp);
  	kfree(bh);
b3b94faa5   David Teigland   [GFS2] The core o...
1204
1205
  	return error;
  }
479c427dd   Steven Whitehouse   GFS2: Clean up ACLs
1206
  int gfs2_xattr_acl_chmod(struct gfs2_inode *ip, struct iattr *attr, char *data)
b3b94faa5   David Teigland   [GFS2] The core o...
1207
  {
ab9bbda02   Steven Whitehouse   GFS2: Use ->dirty...
1208
1209
  	struct inode *inode = &ip->i_inode;
  	struct gfs2_sbd *sdp = GFS2_SB(inode);
479c427dd   Steven Whitehouse   GFS2: Clean up ACLs
1210
  	struct gfs2_ea_location el;
b3b94faa5   David Teigland   [GFS2] The core o...
1211
  	int error;
479c427dd   Steven Whitehouse   GFS2: Clean up ACLs
1212
1213
1214
1215
1216
  	error = gfs2_ea_find(ip, GFS2_EATYPE_SYS, GFS2_POSIX_ACL_ACCESS, &el);
  	if (error)
  		return error;
  
  	if (GFS2_EA_IS_STUFFED(el.el_ea)) {
e412bdb12   Steven Whitehouse   GFS2: Fix gfs2_xa...
1217
1218
1219
1220
1221
1222
1223
  		error = gfs2_trans_begin(sdp, RES_DINODE + RES_EATTR, 0);
  		if (error == 0) {
  			gfs2_trans_add_bh(ip->i_gl, el.el_bh, 1);
  			memcpy(GFS2_EA2DATA(el.el_ea), data,
  			       GFS2_EA_DATA_LEN(el.el_ea));
  		}
  	} else {
479c427dd   Steven Whitehouse   GFS2: Clean up ACLs
1224
  		error = ea_acl_chmod_unstuffed(ip, el.el_ea, data);
e412bdb12   Steven Whitehouse   GFS2: Fix gfs2_xa...
1225
  	}
b3b94faa5   David Teigland   [GFS2] The core o...
1226

e412bdb12   Steven Whitehouse   GFS2: Fix gfs2_xa...
1227
  	brelse(el.el_bh);
b3b94faa5   David Teigland   [GFS2] The core o...
1228
1229
  	if (error)
  		return error;
ab9bbda02   Steven Whitehouse   GFS2: Use ->dirty...
1230
  	error = gfs2_setattr_simple(inode, attr);
e412bdb12   Steven Whitehouse   GFS2: Fix gfs2_xa...
1231
  	gfs2_trans_end(sdp);
b3b94faa5   David Teigland   [GFS2] The core o...
1232
1233
1234
1235
1236
  	return error;
  }
  
  static int ea_dealloc_indirect(struct gfs2_inode *ip)
  {
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
1237
  	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
b3b94faa5   David Teigland   [GFS2] The core o...
1238
1239
  	struct gfs2_rgrp_list rlist;
  	struct buffer_head *indbh, *dibh;
b44b84d76   Al Viro   [GFS2] gfs2 misc ...
1240
  	__be64 *eablk, *end;
b3b94faa5   David Teigland   [GFS2] The core o...
1241
  	unsigned int rg_blocks = 0;
cd915493f   Steven Whitehouse   [GFS2] Change all...
1242
  	u64 bstart = 0;
b3b94faa5   David Teigland   [GFS2] The core o...
1243
1244
1245
1246
1247
1248
  	unsigned int blen = 0;
  	unsigned int blks = 0;
  	unsigned int x;
  	int error;
  
  	memset(&rlist, 0, sizeof(struct gfs2_rgrp_list));
3767ac21f   Steven Whitehouse   GFS2: Move di_eat...
1249
  	error = gfs2_meta_read(ip->i_gl, ip->i_eattr, DIO_WAIT, &indbh);
b3b94faa5   David Teigland   [GFS2] The core o...
1250
1251
1252
1253
1254
1255
1256
  	if (error)
  		return error;
  
  	if (gfs2_metatype_check(sdp, indbh, GFS2_METATYPE_IN)) {
  		error = -EIO;
  		goto out;
  	}
b44b84d76   Al Viro   [GFS2] gfs2 misc ...
1257
  	eablk = (__be64 *)(indbh->b_data + sizeof(struct gfs2_meta_header));
b3b94faa5   David Teigland   [GFS2] The core o...
1258
1259
1260
  	end = eablk + sdp->sd_inptrs;
  
  	for (; eablk < end; eablk++) {
cd915493f   Steven Whitehouse   [GFS2] Change all...
1261
  		u64 bn;
b3b94faa5   David Teigland   [GFS2] The core o...
1262
1263
1264
1265
1266
1267
1268
1269
1270
  
  		if (!*eablk)
  			break;
  		bn = be64_to_cpu(*eablk);
  
  		if (bstart + blen == bn)
  			blen++;
  		else {
  			if (bstart)
70b0c3656   Steven Whitehouse   GFS2: Use cached ...
1271
  				gfs2_rlist_add(ip, &rlist, bstart);
b3b94faa5   David Teigland   [GFS2] The core o...
1272
1273
1274
1275
1276
1277
  			bstart = bn;
  			blen = 1;
  		}
  		blks++;
  	}
  	if (bstart)
70b0c3656   Steven Whitehouse   GFS2: Use cached ...
1278
  		gfs2_rlist_add(ip, &rlist, bstart);
b3b94faa5   David Teigland   [GFS2] The core o...
1279
1280
  	else
  		goto out;
fe6c991c5   Bob Peterson   [GFS2] Get rid of...
1281
  	gfs2_rlist_alloc(&rlist, LM_ST_EXCLUSIVE);
b3b94faa5   David Teigland   [GFS2] The core o...
1282
1283
1284
  
  	for (x = 0; x < rlist.rl_rgrps; x++) {
  		struct gfs2_rgrpd *rgd;
5c676f6d3   Steven Whitehouse   [GFS2] Macros rem...
1285
  		rgd = rlist.rl_ghs[x].gh_gl->gl_object;
bb8d8a6f5   Steven Whitehouse   [GFS2] Fix sign p...
1286
  		rg_blocks += rgd->rd_length;
b3b94faa5   David Teigland   [GFS2] The core o...
1287
1288
1289
1290
1291
  	}
  
  	error = gfs2_glock_nq_m(rlist.rl_rgrps, rlist.rl_ghs);
  	if (error)
  		goto out_rlist_free;
cca195c5c   Steven Whitehouse   [GFS2] Extended a...
1292
1293
  	error = gfs2_trans_begin(sdp, rg_blocks + RES_DINODE + RES_INDIRECT +
  				 RES_STATFS + RES_QUOTA, blks);
b3b94faa5   David Teigland   [GFS2] The core o...
1294
1295
  	if (error)
  		goto out_gunlock;
d4e9c4c3b   Steven Whitehouse   [GFS2] Add an add...
1296
  	gfs2_trans_add_bh(ip->i_gl, indbh, 1);
b3b94faa5   David Teigland   [GFS2] The core o...
1297

b44b84d76   Al Viro   [GFS2] gfs2 misc ...
1298
  	eablk = (__be64 *)(indbh->b_data + sizeof(struct gfs2_meta_header));
b3b94faa5   David Teigland   [GFS2] The core o...
1299
1300
1301
1302
  	bstart = 0;
  	blen = 0;
  
  	for (; eablk < end; eablk++) {
cd915493f   Steven Whitehouse   [GFS2] Change all...
1303
  		u64 bn;
b3b94faa5   David Teigland   [GFS2] The core o...
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
  
  		if (!*eablk)
  			break;
  		bn = be64_to_cpu(*eablk);
  
  		if (bstart + blen == bn)
  			blen++;
  		else {
  			if (bstart)
  				gfs2_free_meta(ip, bstart, blen);
  			bstart = bn;
  			blen = 1;
  		}
  
  		*eablk = 0;
77658aad2   Steven Whitehouse   [GFS2] Eliminate ...
1319
  		gfs2_add_inode_blocks(&ip->i_inode, -1);
b3b94faa5   David Teigland   [GFS2] The core o...
1320
1321
1322
  	}
  	if (bstart)
  		gfs2_free_meta(ip, bstart, blen);
383f01fbf   Steven Whitehouse   GFS2: Banish stru...
1323
  	ip->i_diskflags &= ~GFS2_DIF_EA_INDIRECT;
b3b94faa5   David Teigland   [GFS2] The core o...
1324
1325
1326
  
  	error = gfs2_meta_inode_buffer(ip, &dibh);
  	if (!error) {
d4e9c4c3b   Steven Whitehouse   [GFS2] Add an add...
1327
  		gfs2_trans_add_bh(ip->i_gl, dibh, 1);
539e5d6b7   Steven Whitehouse   [GFS2] Change arg...
1328
  		gfs2_dinode_out(ip, dibh->b_data);
b3b94faa5   David Teigland   [GFS2] The core o...
1329
1330
1331
1332
  		brelse(dibh);
  	}
  
  	gfs2_trans_end(sdp);
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
1333
  out_gunlock:
b3b94faa5   David Teigland   [GFS2] The core o...
1334
  	gfs2_glock_dq_m(rlist.rl_rgrps, rlist.rl_ghs);
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
1335
  out_rlist_free:
b3b94faa5   David Teigland   [GFS2] The core o...
1336
  	gfs2_rlist_free(&rlist);
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
1337
  out:
b3b94faa5   David Teigland   [GFS2] The core o...
1338
  	brelse(indbh);
b3b94faa5   David Teigland   [GFS2] The core o...
1339
1340
1341
1342
1343
  	return error;
  }
  
  static int ea_dealloc_block(struct gfs2_inode *ip)
  {
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
1344
  	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
b3b94faa5   David Teigland   [GFS2] The core o...
1345
1346
  	struct gfs2_rgrpd *rgd;
  	struct buffer_head *dibh;
564e12b11   Bob Peterson   GFS2: decouple qu...
1347
  	struct gfs2_holder gh;
b3b94faa5   David Teigland   [GFS2] The core o...
1348
  	int error;
3767ac21f   Steven Whitehouse   GFS2: Move di_eat...
1349
  	rgd = gfs2_blk2rgrpd(sdp, ip->i_eattr);
b3b94faa5   David Teigland   [GFS2] The core o...
1350
1351
1352
1353
  	if (!rgd) {
  		gfs2_consist_inode(ip);
  		return -EIO;
  	}
564e12b11   Bob Peterson   GFS2: decouple qu...
1354
  	error = gfs2_glock_nq_init(rgd->rd_gl, LM_ST_EXCLUSIVE, 0, &gh);
b3b94faa5   David Teigland   [GFS2] The core o...
1355
1356
  	if (error)
  		return error;
cca195c5c   Steven Whitehouse   [GFS2] Extended a...
1357
1358
  	error = gfs2_trans_begin(sdp, RES_RG_BIT + RES_DINODE + RES_STATFS +
  				 RES_QUOTA, 1);
b3b94faa5   David Teigland   [GFS2] The core o...
1359
1360
  	if (error)
  		goto out_gunlock;
3767ac21f   Steven Whitehouse   GFS2: Move di_eat...
1361
  	gfs2_free_meta(ip, ip->i_eattr, 1);
b3b94faa5   David Teigland   [GFS2] The core o...
1362

3767ac21f   Steven Whitehouse   GFS2: Move di_eat...
1363
  	ip->i_eattr = 0;
77658aad2   Steven Whitehouse   [GFS2] Eliminate ...
1364
  	gfs2_add_inode_blocks(&ip->i_inode, -1);
b3b94faa5   David Teigland   [GFS2] The core o...
1365
1366
1367
  
  	error = gfs2_meta_inode_buffer(ip, &dibh);
  	if (!error) {
d4e9c4c3b   Steven Whitehouse   [GFS2] Add an add...
1368
  		gfs2_trans_add_bh(ip->i_gl, dibh, 1);
539e5d6b7   Steven Whitehouse   [GFS2] Change arg...
1369
  		gfs2_dinode_out(ip, dibh->b_data);
b3b94faa5   David Teigland   [GFS2] The core o...
1370
1371
1372
1373
  		brelse(dibh);
  	}
  
  	gfs2_trans_end(sdp);
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
1374
  out_gunlock:
564e12b11   Bob Peterson   GFS2: decouple qu...
1375
  	gfs2_glock_dq_uninit(&gh);
b3b94faa5   David Teigland   [GFS2] The core o...
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
  	return error;
  }
  
  /**
   * gfs2_ea_dealloc - deallocate the extended attribute fork
   * @ip: the inode
   *
   * Returns: errno
   */
  
  int gfs2_ea_dealloc(struct gfs2_inode *ip)
  {
564e12b11   Bob Peterson   GFS2: decouple qu...
1388
  	struct gfs2_qadata *qa;
b3b94faa5   David Teigland   [GFS2] The core o...
1389
  	int error;
564e12b11   Bob Peterson   GFS2: decouple qu...
1390
1391
  	qa = gfs2_qadata_get(ip);
  	if (!qa)
182fe5abd   Cyrill Gorcunov   [GFS2] possible n...
1392
  		return -ENOMEM;
b3b94faa5   David Teigland   [GFS2] The core o...
1393
1394
1395
1396
  
  	error = gfs2_quota_hold(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
  	if (error)
  		goto out_alloc;
b3b94faa5   David Teigland   [GFS2] The core o...
1397
1398
  	error = ea_foreach(ip, ea_dealloc_unstuffed, NULL);
  	if (error)
8339ee543   Steven Whitehouse   GFS2: Make resour...
1399
  		goto out_quota;
b3b94faa5   David Teigland   [GFS2] The core o...
1400

383f01fbf   Steven Whitehouse   GFS2: Banish stru...
1401
  	if (ip->i_diskflags & GFS2_DIF_EA_INDIRECT) {
b3b94faa5   David Teigland   [GFS2] The core o...
1402
1403
  		error = ea_dealloc_indirect(ip);
  		if (error)
8339ee543   Steven Whitehouse   GFS2: Make resour...
1404
  			goto out_quota;
b3b94faa5   David Teigland   [GFS2] The core o...
1405
1406
1407
  	}
  
  	error = ea_dealloc_block(ip);
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
1408
  out_quota:
b3b94faa5   David Teigland   [GFS2] The core o...
1409
  	gfs2_quota_unhold(ip);
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
1410
  out_alloc:
564e12b11   Bob Peterson   GFS2: decouple qu...
1411
  	gfs2_qadata_put(ip);
b3b94faa5   David Teigland   [GFS2] The core o...
1412
1413
  	return error;
  }
b7bb0a129   Stephen Hemminger   gfs: constify xat...
1414
  static const struct xattr_handler gfs2_xattr_user_handler = {
40b78a322   Steven Whitehouse   GFS2: Clean up of...
1415
  	.prefix = XATTR_USER_PREFIX,
431547b3c   Christoph Hellwig   sanitize xattr ha...
1416
1417
1418
  	.flags  = GFS2_EATYPE_USR,
  	.get    = gfs2_xattr_get,
  	.set    = gfs2_xattr_set,
40b78a322   Steven Whitehouse   GFS2: Clean up of...
1419
  };
b7bb0a129   Stephen Hemminger   gfs: constify xat...
1420
  static const struct xattr_handler gfs2_xattr_security_handler = {
40b78a322   Steven Whitehouse   GFS2: Clean up of...
1421
  	.prefix = XATTR_SECURITY_PREFIX,
431547b3c   Christoph Hellwig   sanitize xattr ha...
1422
1423
1424
  	.flags  = GFS2_EATYPE_SECURITY,
  	.get    = gfs2_xattr_get,
  	.set    = gfs2_xattr_set,
40b78a322   Steven Whitehouse   GFS2: Clean up of...
1425
  };
b7bb0a129   Stephen Hemminger   gfs: constify xat...
1426
  const struct xattr_handler *gfs2_xattr_handlers[] = {
40b78a322   Steven Whitehouse   GFS2: Clean up of...
1427
1428
1429
1430
1431
  	&gfs2_xattr_user_handler,
  	&gfs2_xattr_security_handler,
  	&gfs2_xattr_system_handler,
  	NULL,
  };