Blame view

fs/gfs2/inode.c 42.7 KB
b3b94faa5   David Teigland   [GFS2] The core o...
1
2
  /*
   * Copyright (C) Sistina Software, Inc.  1997-2003 All rights reserved.
f2741d989   Steven Whitehouse   GFS2: Move all lo...
3
   * Copyright (C) 2004-2011 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/namei.h>
b3b94faa5   David Teigland   [GFS2] The core o...
14
15
16
  #include <linux/mm.h>
  #include <linux/xattr.h>
  #include <linux/posix_acl.h>
5c676f6d3   Steven Whitehouse   [GFS2] Macros rem...
17
  #include <linux/gfs2_ondisk.h>
71b86f562   Steven Whitehouse   [GFS2] Further up...
18
  #include <linux/crc32.h>
e9079cce2   Steven Whitehouse   GFS2: Support for...
19
  #include <linux/fiemap.h>
194c011fc   Steven Whitehouse   GFS2: Move most o...
20
  #include <linux/security.h>
b3b94faa5   David Teigland   [GFS2] The core o...
21
22
23
  #include <asm/uaccess.h>
  
  #include "gfs2.h"
5c676f6d3   Steven Whitehouse   [GFS2] Macros rem...
24
  #include "incore.h"
b3b94faa5   David Teigland   [GFS2] The core o...
25
26
27
  #include "acl.h"
  #include "bmap.h"
  #include "dir.h"
307cf6e63   Steven Whitehouse   GFS2: Rename eatt...
28
  #include "xattr.h"
b3b94faa5   David Teigland   [GFS2] The core o...
29
30
31
  #include "glock.h"
  #include "inode.h"
  #include "meta_io.h"
b3b94faa5   David Teigland   [GFS2] The core o...
32
33
34
  #include "quota.h"
  #include "rgrp.h"
  #include "trans.h"
5c676f6d3   Steven Whitehouse   [GFS2] Macros rem...
35
  #include "util.h"
b27605837   Steven Whitehouse   GFS2: Rationalise...
36
  #include "super.h"
194c011fc   Steven Whitehouse   GFS2: Move most o...
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
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
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
  #include "glops.h"
  
  struct gfs2_skip_data {
  	u64 no_addr;
  	int skipped;
  	int non_block;
  };
  
  static int iget_test(struct inode *inode, void *opaque)
  {
  	struct gfs2_inode *ip = GFS2_I(inode);
  	struct gfs2_skip_data *data = opaque;
  
  	if (ip->i_no_addr == data->no_addr) {
  		if (data->non_block &&
  		    inode->i_state & (I_FREEING|I_CLEAR|I_WILL_FREE)) {
  			data->skipped = 1;
  			return 0;
  		}
  		return 1;
  	}
  	return 0;
  }
  
  static int iget_set(struct inode *inode, void *opaque)
  {
  	struct gfs2_inode *ip = GFS2_I(inode);
  	struct gfs2_skip_data *data = opaque;
  
  	if (data->skipped)
  		return -ENOENT;
  	inode->i_ino = (unsigned long)(data->no_addr);
  	ip->i_no_addr = data->no_addr;
  	return 0;
  }
  
  struct inode *gfs2_ilookup(struct super_block *sb, u64 no_addr, int non_block)
  {
  	unsigned long hash = (unsigned long)no_addr;
  	struct gfs2_skip_data data;
  
  	data.no_addr = no_addr;
  	data.skipped = 0;
  	data.non_block = non_block;
  	return ilookup5(sb, hash, iget_test, &data);
  }
  
  static struct inode *gfs2_iget(struct super_block *sb, u64 no_addr,
  			       int non_block)
  {
  	struct gfs2_skip_data data;
  	unsigned long hash = (unsigned long)no_addr;
  
  	data.no_addr = no_addr;
  	data.skipped = 0;
  	data.non_block = non_block;
  	return iget5_locked(sb, hash, iget_test, iget_set, &data);
  }
  
  /**
   * gfs2_set_iop - Sets inode operations
   * @inode: The inode with correct i_mode filled in
   *
   * GFS2 lookup code fills in vfs inode contents based on info obtained
   * from directory entry inside gfs2_inode_lookup().
   */
  
  static void gfs2_set_iop(struct inode *inode)
  {
  	struct gfs2_sbd *sdp = GFS2_SB(inode);
  	umode_t mode = inode->i_mode;
  
  	if (S_ISREG(mode)) {
  		inode->i_op = &gfs2_file_iops;
  		if (gfs2_localflocks(sdp))
  			inode->i_fop = &gfs2_file_fops_nolock;
  		else
  			inode->i_fop = &gfs2_file_fops;
  	} else if (S_ISDIR(mode)) {
  		inode->i_op = &gfs2_dir_iops;
  		if (gfs2_localflocks(sdp))
  			inode->i_fop = &gfs2_dir_fops_nolock;
  		else
  			inode->i_fop = &gfs2_dir_fops;
  	} else if (S_ISLNK(mode)) {
  		inode->i_op = &gfs2_symlink_iops;
  	} else {
  		inode->i_op = &gfs2_file_iops;
  		init_special_inode(inode, inode->i_mode, inode->i_rdev);
  	}
  }
  
  /**
   * gfs2_inode_lookup - Lookup an inode
   * @sb: The super block
   * @no_addr: The inode number
   * @type: The type of the inode
   * non_block: Can we block on inodes that are being freed?
   *
   * Returns: A VFS inode, or an error
   */
  
  struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned int type,
  				u64 no_addr, u64 no_formal_ino, int non_block)
  {
  	struct inode *inode;
  	struct gfs2_inode *ip;
  	struct gfs2_glock *io_gl = NULL;
  	int error;
  
  	inode = gfs2_iget(sb, no_addr, non_block);
  	ip = GFS2_I(inode);
  
  	if (!inode)
  		return ERR_PTR(-ENOBUFS);
  
  	if (inode->i_state & I_NEW) {
  		struct gfs2_sbd *sdp = GFS2_SB(inode);
  		ip->i_no_formal_ino = no_formal_ino;
  
  		error = gfs2_glock_get(sdp, no_addr, &gfs2_inode_glops, CREATE, &ip->i_gl);
  		if (unlikely(error))
  			goto fail;
  		ip->i_gl->gl_object = ip;
  
  		error = gfs2_glock_get(sdp, no_addr, &gfs2_iopen_glops, CREATE, &io_gl);
  		if (unlikely(error))
  			goto fail_put;
  
  		set_bit(GIF_INVALID, &ip->i_flags);
  		error = gfs2_glock_nq_init(io_gl, LM_ST_SHARED, GL_EXACT, &ip->i_iopen_gh);
  		if (unlikely(error))
  			goto fail_iopen;
  
  		ip->i_iopen_gh.gh_gl->gl_object = ip;
  		gfs2_glock_put(io_gl);
  		io_gl = NULL;
  
  		if (type == DT_UNKNOWN) {
  			/* Inode glock must be locked already */
  			error = gfs2_inode_refresh(GFS2_I(inode));
  			if (error)
  				goto fail_refresh;
  		} else {
  			inode->i_mode = DT2IF(type);
  		}
  
  		gfs2_set_iop(inode);
  		unlock_new_inode(inode);
  	}
  
  	return inode;
  
  fail_refresh:
  	ip->i_iopen_gh.gh_gl->gl_object = NULL;
  	gfs2_glock_dq_uninit(&ip->i_iopen_gh);
  fail_iopen:
  	if (io_gl)
  		gfs2_glock_put(io_gl);
  fail_put:
  	ip->i_gl->gl_object = NULL;
  	gfs2_glock_put(ip->i_gl);
  fail:
  	iget_failed(inode);
  	return ERR_PTR(error);
  }
  
  struct inode *gfs2_lookup_by_inum(struct gfs2_sbd *sdp, u64 no_addr,
  				  u64 *no_formal_ino, unsigned int blktype)
  {
  	struct super_block *sb = sdp->sd_vfs;
  	struct gfs2_holder i_gh;
  	struct inode *inode = NULL;
  	int error;
  
  	/* Must not read in block until block type is verified */
  	error = gfs2_glock_nq_num(sdp, no_addr, &gfs2_inode_glops,
  				  LM_ST_EXCLUSIVE, GL_SKIP, &i_gh);
  	if (error)
  		return ERR_PTR(error);
  
  	error = gfs2_check_blk_type(sdp, no_addr, blktype);
  	if (error)
  		goto fail;
  
  	inode = gfs2_inode_lookup(sb, DT_UNKNOWN, no_addr, 0, 1);
  	if (IS_ERR(inode))
  		goto fail;
  
  	/* Two extra checks for NFS only */
  	if (no_formal_ino) {
  		error = -ESTALE;
  		if (GFS2_I(inode)->i_no_formal_ino != *no_formal_ino)
  			goto fail_iput;
  
  		error = -EIO;
  		if (GFS2_I(inode)->i_diskflags & GFS2_DIF_SYSTEM)
  			goto fail_iput;
  
  		error = 0;
  	}
  
  fail:
  	gfs2_glock_dq_uninit(&i_gh);
  	return error ? ERR_PTR(error) : inode;
  fail_iput:
  	iput(inode);
  	goto fail;
  }
  
  
  struct inode *gfs2_lookup_simple(struct inode *dip, const char *name)
  {
  	struct qstr qstr;
  	struct inode *inode;
  	gfs2_str2qstr(&qstr, name);
  	inode = gfs2_lookupi(dip, &qstr, 1);
  	/* gfs2_lookupi has inconsistent callers: vfs
  	 * related routines expect NULL for no entry found,
  	 * gfs2_lookup_simple callers expect ENOENT
  	 * and do not check for NULL.
  	 */
  	if (inode == NULL)
  		return ERR_PTR(-ENOENT);
  	else
  		return inode;
  }
  
  
  /**
   * gfs2_lookupi - Look up a filename in a directory and return its inode
   * @d_gh: An initialized holder for the directory glock
   * @name: The name of the inode to look for
   * @is_root: If 1, ignore the caller's permissions
   * @i_gh: An uninitialized holder for the new inode glock
   *
   * This can be called via the VFS filldir function when NFS is doing
   * a readdirplus and the inode which its intending to stat isn't
   * already in cache. In this case we must not take the directory glock
   * again, since the readdir call will have already taken that lock.
   *
   * Returns: errno
   */
  
  struct inode *gfs2_lookupi(struct inode *dir, const struct qstr *name,
  			   int is_root)
  {
  	struct super_block *sb = dir->i_sb;
  	struct gfs2_inode *dip = GFS2_I(dir);
  	struct gfs2_holder d_gh;
  	int error = 0;
  	struct inode *inode = NULL;
  	int unlock = 0;
  
  	if (!name->len || name->len > GFS2_FNAMESIZE)
  		return ERR_PTR(-ENAMETOOLONG);
  
  	if ((name->len == 1 && memcmp(name->name, ".", 1) == 0) ||
  	    (name->len == 2 && memcmp(name->name, "..", 2) == 0 &&
  	     dir == sb->s_root->d_inode)) {
  		igrab(dir);
  		return dir;
  	}
  
  	if (gfs2_glock_is_locked_by_me(dip->i_gl) == NULL) {
  		error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &d_gh);
  		if (error)
  			return ERR_PTR(error);
  		unlock = 1;
  	}
  
  	if (!is_root) {
10556cb21   Al Viro   ->permission() sa...
309
  		error = gfs2_permission(dir, MAY_EXEC);
194c011fc   Steven Whitehouse   GFS2: Move most o...
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
  		if (error)
  			goto out;
  	}
  
  	inode = gfs2_dir_search(dir, name);
  	if (IS_ERR(inode))
  		error = PTR_ERR(inode);
  out:
  	if (unlock)
  		gfs2_glock_dq_uninit(&d_gh);
  	if (error == -ENOENT)
  		return NULL;
  	return inode ? inode : ERR_PTR(error);
  }
  
  /**
   * create_ok - OK to create a new on-disk inode here?
   * @dip:  Directory in which dinode is to be created
   * @name:  Name of new dinode
   * @mode:
   *
   * Returns: errno
   */
  
  static int create_ok(struct gfs2_inode *dip, const struct qstr *name,
175a4eb7e   Al Viro   fs: propagate umo...
335
  		     umode_t mode)
194c011fc   Steven Whitehouse   GFS2: Move most o...
336
337
  {
  	int error;
10556cb21   Al Viro   ->permission() sa...
338
  	error = gfs2_permission(&dip->i_inode, MAY_WRITE | MAY_EXEC);
194c011fc   Steven Whitehouse   GFS2: Move most o...
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
  	if (error)
  		return error;
  
  	/*  Don't create entries in an unlinked directory  */
  	if (!dip->i_inode.i_nlink)
  		return -ENOENT;
  
  	error = gfs2_dir_check(&dip->i_inode, name, NULL);
  	switch (error) {
  	case -ENOENT:
  		error = 0;
  		break;
  	case 0:
  		return -EEXIST;
  	default:
  		return error;
  	}
  
  	if (dip->i_entries == (u32)-1)
  		return -EFBIG;
  	if (S_ISDIR(mode) && dip->i_inode.i_nlink == (u32)-1)
  		return -EMLINK;
  
  	return 0;
  }
175a4eb7e   Al Viro   fs: propagate umo...
364
  static void munge_mode_uid_gid(struct gfs2_inode *dip, umode_t *mode,
194c011fc   Steven Whitehouse   GFS2: Move most o...
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
  			       unsigned int *uid, unsigned int *gid)
  {
  	if (GFS2_SB(&dip->i_inode)->sd_args.ar_suiddir &&
  	    (dip->i_inode.i_mode & S_ISUID) && dip->i_inode.i_uid) {
  		if (S_ISDIR(*mode))
  			*mode |= S_ISUID;
  		else if (dip->i_inode.i_uid != current_fsuid())
  			*mode &= ~07111;
  		*uid = dip->i_inode.i_uid;
  	} else
  		*uid = current_fsuid();
  
  	if (dip->i_inode.i_mode & S_ISGID) {
  		if (S_ISDIR(*mode))
  			*mode |= S_ISGID;
  		*gid = dip->i_inode.i_gid;
  	} else
  		*gid = current_fsgid();
  }
  
  static int alloc_dinode(struct gfs2_inode *dip, u64 *no_addr, u64 *generation)
  {
  	struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
  	int error;
6a8099ed5   Steven Whitehouse   GFS2: Fix multi-b...
389
  	int dblocks = 1;
194c011fc   Steven Whitehouse   GFS2: Move most o...
390

564e12b11   Bob Peterson   GFS2: decouple qu...
391
392
393
394
  	error = gfs2_rindex_update(sdp);
  	if (error)
  		fs_warn(sdp, "rindex update returns %d
  ", error);
194c011fc   Steven Whitehouse   GFS2: Move most o...
395

564e12b11   Bob Peterson   GFS2: decouple qu...
396
  	error = gfs2_inplace_reserve(dip, RES_DINODE);
194c011fc   Steven Whitehouse   GFS2: Move most o...
397
398
399
400
401
402
  	if (error)
  		goto out;
  
  	error = gfs2_trans_begin(sdp, RES_RG_BIT + RES_STATFS, 0);
  	if (error)
  		goto out_ipreserv;
6e87ed0fc   Bob Peterson   GFS2: move toward...
403
  	error = gfs2_alloc_blocks(dip, no_addr, &dblocks, 1, generation);
194c011fc   Steven Whitehouse   GFS2: Move most o...
404
405
406
407
408
409
  
  	gfs2_trans_end(sdp);
  
  out_ipreserv:
  	gfs2_inplace_release(dip);
  out:
194c011fc   Steven Whitehouse   GFS2: Move most o...
410
411
  	return error;
  }
f2741d989   Steven Whitehouse   GFS2: Move all lo...
412
413
  static void gfs2_init_dir(struct buffer_head *dibh,
  			  const struct gfs2_inode *parent)
e2d0a13bb   Steven Whitehouse   GFS2: Clean up mkdir
414
415
416
417
418
419
420
421
422
423
424
425
426
427
  {
  	struct gfs2_dinode *di = (struct gfs2_dinode *)dibh->b_data;
  	struct gfs2_dirent *dent = (struct gfs2_dirent *)(di+1);
  
  	gfs2_qstr2dirent(&gfs2_qdot, GFS2_DIRENT_SIZE(gfs2_qdot.len), dent);
  	dent->de_inum = di->di_num; /* already GFS2 endian */
  	dent->de_type = cpu_to_be16(DT_DIR);
  
  	dent = (struct gfs2_dirent *)((char*)dent + GFS2_DIRENT_SIZE(1));
  	gfs2_qstr2dirent(&gfs2_qdotdot, dibh->b_size - GFS2_DIRENT_SIZE(1) - sizeof(struct gfs2_dinode), dent);
  	gfs2_inum_out(parent, dent);
  	dent->de_type = cpu_to_be16(DT_DIR);
  	
  }
194c011fc   Steven Whitehouse   GFS2: Move most o...
428
429
  /**
   * init_dinode - Fill in a new dinode structure
f2741d989   Steven Whitehouse   GFS2: Move all lo...
430
   * @dip: The directory this inode is being created in
194c011fc   Steven Whitehouse   GFS2: Move most o...
431
   * @gl: The glock covering the new inode
f2741d989   Steven Whitehouse   GFS2: Move all lo...
432
433
434
435
436
437
438
439
440
   * @inum: The inode number
   * @mode: The file permissions
   * @uid: The uid of the new inode
   * @gid: The gid of the new inode
   * @generation: The generation number of the new inode
   * @dev: The device number (if a device node)
   * @symname: The symlink destination (if a symlink)
   * @size: The inode size (ignored for directories)
   * @bhp: The buffer head (returned to caller)
194c011fc   Steven Whitehouse   GFS2: Move most o...
441
442
443
444
   *
   */
  
  static void init_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl,
175a4eb7e   Al Viro   fs: propagate umo...
445
  			const struct gfs2_inum_host *inum, umode_t mode,
194c011fc   Steven Whitehouse   GFS2: Move most o...
446
  			unsigned int uid, unsigned int gid,
160b4026d   Steven Whitehouse   GFS2: Clean up sy...
447
448
  			const u64 *generation, dev_t dev, const char *symname,
  			unsigned size, struct buffer_head **bhp)
194c011fc   Steven Whitehouse   GFS2: Move most o...
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
  {
  	struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
  	struct gfs2_dinode *di;
  	struct buffer_head *dibh;
  	struct timespec tv = CURRENT_TIME;
  
  	dibh = gfs2_meta_new(gl, inum->no_addr);
  	gfs2_trans_add_bh(gl, dibh, 1);
  	gfs2_metatype_set(dibh, GFS2_METATYPE_DI, GFS2_FORMAT_DI);
  	gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode));
  	di = (struct gfs2_dinode *)dibh->b_data;
  
  	di->di_num.no_formal_ino = cpu_to_be64(inum->no_formal_ino);
  	di->di_num.no_addr = cpu_to_be64(inum->no_addr);
  	di->di_mode = cpu_to_be32(mode);
  	di->di_uid = cpu_to_be32(uid);
  	di->di_gid = cpu_to_be32(gid);
  	di->di_nlink = 0;
160b4026d   Steven Whitehouse   GFS2: Clean up sy...
467
  	di->di_size = cpu_to_be64(size);
194c011fc   Steven Whitehouse   GFS2: Move most o...
468
469
470
471
472
473
474
  	di->di_blocks = cpu_to_be64(1);
  	di->di_atime = di->di_mtime = di->di_ctime = cpu_to_be64(tv.tv_sec);
  	di->di_major = cpu_to_be32(MAJOR(dev));
  	di->di_minor = cpu_to_be32(MINOR(dev));
  	di->di_goal_meta = di->di_goal_data = cpu_to_be64(inum->no_addr);
  	di->di_generation = cpu_to_be64(*generation);
  	di->di_flags = 0;
194c011fc   Steven Whitehouse   GFS2: Move most o...
475
476
477
478
479
480
481
482
483
484
485
486
487
  	di->__pad1 = 0;
  	di->di_payload_format = cpu_to_be32(S_ISDIR(mode) ? GFS2_FORMAT_DE : 0);
  	di->di_height = 0;
  	di->__pad2 = 0;
  	di->__pad3 = 0;
  	di->di_depth = 0;
  	di->di_entries = 0;
  	memset(&di->__pad4, 0, sizeof(di->__pad4));
  	di->di_eattr = 0;
  	di->di_atime_nsec = cpu_to_be32(tv.tv_nsec);
  	di->di_mtime_nsec = cpu_to_be32(tv.tv_nsec);
  	di->di_ctime_nsec = cpu_to_be32(tv.tv_nsec);
  	memset(&di->di_reserved, 0, sizeof(di->di_reserved));
160b4026d   Steven Whitehouse   GFS2: Clean up sy...
488
489
490
  
  	switch(mode & S_IFMT) {	
  	case S_IFREG:
e2d0a13bb   Steven Whitehouse   GFS2: Clean up mkdir
491
492
493
  		if ((dip->i_diskflags & GFS2_DIF_INHERIT_JDATA) ||
  		    gfs2_tune_get(sdp, gt_new_files_jdata))
  			di->di_flags |= cpu_to_be32(GFS2_DIF_JDATA);
160b4026d   Steven Whitehouse   GFS2: Clean up sy...
494
495
  		break;
  	case S_IFDIR:
e2d0a13bb   Steven Whitehouse   GFS2: Clean up mkdir
496
497
498
499
500
501
  		di->di_flags |= cpu_to_be32(dip->i_diskflags &
  					    GFS2_DIF_INHERIT_JDATA);
  		di->di_flags |= cpu_to_be32(GFS2_DIF_JDATA);
  		di->di_size = cpu_to_be64(sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode));
  		di->di_entries = cpu_to_be32(2);
  		gfs2_init_dir(dibh, dip);
160b4026d   Steven Whitehouse   GFS2: Clean up sy...
502
503
504
505
  		break;
  	case S_IFLNK:
  		memcpy(dibh->b_data + sizeof(struct gfs2_dinode), symname, size);
  		break;
e2d0a13bb   Steven Whitehouse   GFS2: Clean up mkdir
506
  	}
194c011fc   Steven Whitehouse   GFS2: Move most o...
507
508
509
510
511
512
  	set_buffer_uptodate(dibh);
  
  	*bhp = dibh;
  }
  
  static int make_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl,
175a4eb7e   Al Viro   fs: propagate umo...
513
  		       umode_t mode, const struct gfs2_inum_host *inum,
160b4026d   Steven Whitehouse   GFS2: Clean up sy...
514
515
  		       const u64 *generation, dev_t dev, const char *symname,
  		       unsigned int size, struct buffer_head **bhp)
194c011fc   Steven Whitehouse   GFS2: Move most o...
516
517
518
519
520
521
  {
  	struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
  	unsigned int uid, gid;
  	int error;
  
  	munge_mode_uid_gid(dip, &mode, &uid, &gid);
564e12b11   Bob Peterson   GFS2: decouple qu...
522
  	if (!gfs2_qadata_get(dip))
194c011fc   Steven Whitehouse   GFS2: Move most o...
523
524
525
526
527
528
529
530
531
532
533
534
535
  		return -ENOMEM;
  
  	error = gfs2_quota_lock(dip, uid, gid);
  	if (error)
  		goto out;
  
  	error = gfs2_quota_check(dip, uid, gid);
  	if (error)
  		goto out_quota;
  
  	error = gfs2_trans_begin(sdp, RES_DINODE + RES_QUOTA, 0);
  	if (error)
  		goto out_quota;
160b4026d   Steven Whitehouse   GFS2: Clean up sy...
536
  	init_dinode(dip, gl, inum, mode, uid, gid, generation, dev, symname, size, bhp);
194c011fc   Steven Whitehouse   GFS2: Move most o...
537
538
539
540
541
542
  	gfs2_quota_change(dip, +1, uid, gid);
  	gfs2_trans_end(sdp);
  
  out_quota:
  	gfs2_quota_unlock(dip);
  out:
564e12b11   Bob Peterson   GFS2: decouple qu...
543
  	gfs2_qadata_put(dip);
194c011fc   Steven Whitehouse   GFS2: Move most o...
544
545
546
547
548
549
550
  	return error;
  }
  
  static int link_dinode(struct gfs2_inode *dip, const struct qstr *name,
  		       struct gfs2_inode *ip)
  {
  	struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
564e12b11   Bob Peterson   GFS2: decouple qu...
551
  	struct gfs2_qadata *qa;
194c011fc   Steven Whitehouse   GFS2: Move most o...
552
553
554
  	int alloc_required;
  	struct buffer_head *dibh;
  	int error;
564e12b11   Bob Peterson   GFS2: decouple qu...
555
556
  	qa = gfs2_qadata_get(dip);
  	if (!qa)
194c011fc   Steven Whitehouse   GFS2: Move most o...
557
558
559
560
561
562
563
564
565
566
567
568
569
  		return -ENOMEM;
  
  	error = gfs2_quota_lock(dip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
  	if (error)
  		goto fail;
  
  	error = alloc_required = gfs2_diradd_alloc_required(&dip->i_inode, name);
  	if (alloc_required < 0)
  		goto fail_quota_locks;
  	if (alloc_required) {
  		error = gfs2_quota_check(dip, dip->i_inode.i_uid, dip->i_inode.i_gid);
  		if (error)
  			goto fail_quota_locks;
564e12b11   Bob Peterson   GFS2: decouple qu...
570
  		error = gfs2_inplace_reserve(dip, sdp->sd_max_dirres);
194c011fc   Steven Whitehouse   GFS2: Move most o...
571
572
573
574
  		if (error)
  			goto fail_quota_locks;
  
  		error = gfs2_trans_begin(sdp, sdp->sd_max_dirres +
54335b1fc   Steven Whitehouse   GFS2: Cache the m...
575
  					 dip->i_rgd->rd_length +
194c011fc   Steven Whitehouse   GFS2: Move most o...
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
  					 2 * RES_DINODE +
  					 RES_STATFS + RES_QUOTA, 0);
  		if (error)
  			goto fail_ipreserv;
  	} else {
  		error = gfs2_trans_begin(sdp, RES_LEAF + 2 * RES_DINODE, 0);
  		if (error)
  			goto fail_quota_locks;
  	}
  
  	error = gfs2_dir_add(&dip->i_inode, name, ip);
  	if (error)
  		goto fail_end_trans;
  
  	error = gfs2_meta_inode_buffer(ip, &dibh);
  	if (error)
  		goto fail_end_trans;
66ad863b4   Steven Whitehouse   GFS2: Fix nlink s...
593
  	set_nlink(&ip->i_inode, S_ISDIR(ip->i_inode.i_mode) ? 2 : 1);
194c011fc   Steven Whitehouse   GFS2: Move most o...
594
595
596
597
598
599
600
601
602
  	gfs2_trans_add_bh(ip->i_gl, dibh, 1);
  	gfs2_dinode_out(ip, dibh->b_data);
  	brelse(dibh);
  	return 0;
  
  fail_end_trans:
  	gfs2_trans_end(sdp);
  
  fail_ipreserv:
54335b1fc   Steven Whitehouse   GFS2: Cache the m...
603
  	gfs2_inplace_release(dip);
194c011fc   Steven Whitehouse   GFS2: Move most o...
604
605
606
607
608
  
  fail_quota_locks:
  	gfs2_quota_unlock(dip);
  
  fail:
564e12b11   Bob Peterson   GFS2: decouple qu...
609
  	gfs2_qadata_put(dip);
194c011fc   Steven Whitehouse   GFS2: Move most o...
610
611
  	return error;
  }
46cc1e5fc   H Hartley Sweeten   GFS2: local funct...
612
  static int gfs2_initxattrs(struct inode *inode, const struct xattr *xattr_array,
9d8f13ba3   Mimi Zohar   security: new sec...
613
  		    void *fs_info)
194c011fc   Steven Whitehouse   GFS2: Move most o...
614
  {
9d8f13ba3   Mimi Zohar   security: new sec...
615
616
617
618
619
620
621
622
623
  	const struct xattr *xattr;
  	int err = 0;
  
  	for (xattr = xattr_array; xattr->name != NULL; xattr++) {
  		err = __gfs2_xattr_set(inode, xattr->name, xattr->value,
  				       xattr->value_len, 0,
  				       GFS2_EATYPE_SECURITY);
  		if (err < 0)
  			break;
194c011fc   Steven Whitehouse   GFS2: Move most o...
624
  	}
194c011fc   Steven Whitehouse   GFS2: Move most o...
625
626
  	return err;
  }
b3b94faa5   David Teigland   [GFS2] The core o...
627

9d8f13ba3   Mimi Zohar   security: new sec...
628
629
630
631
632
633
  static int gfs2_security_init(struct gfs2_inode *dip, struct gfs2_inode *ip,
  			      const struct qstr *qstr)
  {
  	return security_inode_init_security(&ip->i_inode, &dip->i_inode, qstr,
  					    &gfs2_initxattrs, NULL);
  }
b3b94faa5   David Teigland   [GFS2] The core o...
634
  /**
f2741d989   Steven Whitehouse   GFS2: Move all lo...
635
636
637
638
639
640
641
   * gfs2_create_inode - Create a new inode
   * @dir: The parent directory
   * @dentry: The new dentry
   * @mode: The permissions on the new inode
   * @dev: For device nodes, this is the device number
   * @symname: For symlinks, this is the link destination
   * @size: The initial size of the inode (ignored for directories)
194c011fc   Steven Whitehouse   GFS2: Move most o...
642
   *
f2741d989   Steven Whitehouse   GFS2: Move all lo...
643
   * Returns: 0 on success, or error code
194c011fc   Steven Whitehouse   GFS2: Move most o...
644
   */
f2741d989   Steven Whitehouse   GFS2: Move all lo...
645
  static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
175a4eb7e   Al Viro   fs: propagate umo...
646
  			     umode_t mode, dev_t dev, const char *symname,
9a63edd12   Steven Whitehouse   GFS2: Clean up gf...
647
  			     unsigned int size, int excl)
194c011fc   Steven Whitehouse   GFS2: Move most o...
648
  {
f2741d989   Steven Whitehouse   GFS2: Move all lo...
649
650
  	const struct qstr *name = &dentry->d_name;
  	struct gfs2_holder ghs[2];
194c011fc   Steven Whitehouse   GFS2: Move most o...
651
  	struct inode *inode = NULL;
f2741d989   Steven Whitehouse   GFS2: Move all lo...
652
  	struct gfs2_inode *dip = GFS2_I(dir);
194c011fc   Steven Whitehouse   GFS2: Move most o...
653
654
655
656
657
658
659
  	struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
  	struct gfs2_inum_host inum = { .no_addr = 0, .no_formal_ino = 0 };
  	int error;
  	u64 generation;
  	struct buffer_head *bh = NULL;
  
  	if (!name->len || name->len > GFS2_FNAMESIZE)
f2741d989   Steven Whitehouse   GFS2: Move all lo...
660
  		return -ENAMETOOLONG;
194c011fc   Steven Whitehouse   GFS2: Move most o...
661

f2741d989   Steven Whitehouse   GFS2: Move all lo...
662
  	error = gfs2_glock_nq_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, ghs);
194c011fc   Steven Whitehouse   GFS2: Move most o...
663
664
665
666
  	if (error)
  		goto fail;
  
  	error = create_ok(dip, name, mode);
9a63edd12   Steven Whitehouse   GFS2: Clean up gf...
667
668
669
670
671
672
  	if ((error == -EEXIST) && S_ISREG(mode) && !excl) {
  		inode = gfs2_lookupi(dir, &dentry->d_name, 0);
  		gfs2_glock_dq_uninit(ghs);
  		d_instantiate(dentry, inode);
  		return IS_ERR(inode) ? PTR_ERR(inode) : 0;
  	}
194c011fc   Steven Whitehouse   GFS2: Move most o...
673
674
675
676
677
678
679
680
681
682
683
684
  	if (error)
  		goto fail_gunlock;
  
  	error = alloc_dinode(dip, &inum.no_addr, &generation);
  	if (error)
  		goto fail_gunlock;
  	inum.no_formal_ino = generation;
  
  	error = gfs2_glock_nq_num(sdp, inum.no_addr, &gfs2_inode_glops,
  				  LM_ST_EXCLUSIVE, GL_SKIP, ghs + 1);
  	if (error)
  		goto fail_gunlock;
160b4026d   Steven Whitehouse   GFS2: Clean up sy...
685
  	error = make_dinode(dip, ghs[1].gh_gl, mode, &inum, &generation, dev, symname, size, &bh);
194c011fc   Steven Whitehouse   GFS2: Move most o...
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
  	if (error)
  		goto fail_gunlock2;
  
  	inode = gfs2_inode_lookup(dir->i_sb, IF2DT(mode), inum.no_addr,
  				  inum.no_formal_ino, 0);
  	if (IS_ERR(inode))
  		goto fail_gunlock2;
  
  	error = gfs2_inode_refresh(GFS2_I(inode));
  	if (error)
  		goto fail_gunlock2;
  
  	error = gfs2_acl_create(dip, inode);
  	if (error)
  		goto fail_gunlock2;
  
  	error = gfs2_security_init(dip, GFS2_I(inode), name);
  	if (error)
  		goto fail_gunlock2;
  
  	error = link_dinode(dip, name, GFS2_I(inode));
  	if (error)
  		goto fail_gunlock2;
  
  	if (bh)
  		brelse(bh);
f2741d989   Steven Whitehouse   GFS2: Move all lo...
712
713
  
  	gfs2_trans_end(sdp);
564e12b11   Bob Peterson   GFS2: decouple qu...
714
715
716
717
  	/* Check if we reserved space in the rgrp. Function link_dinode may
  	   not, depending on whether alloc is required. */
  	if (dip->i_res)
  		gfs2_inplace_release(dip);
f2741d989   Steven Whitehouse   GFS2: Move all lo...
718
  	gfs2_quota_unlock(dip);
564e12b11   Bob Peterson   GFS2: decouple qu...
719
  	gfs2_qadata_put(dip);
f2741d989   Steven Whitehouse   GFS2: Move all lo...
720
  	mark_inode_dirty(inode);
ab9bbda02   Steven Whitehouse   GFS2: Use ->dirty...
721
  	gfs2_glock_dq_uninit_m(2, ghs);
f2741d989   Steven Whitehouse   GFS2: Move all lo...
722
723
  	d_instantiate(dentry, inode);
  	return 0;
194c011fc   Steven Whitehouse   GFS2: Move most o...
724
725
726
  
  fail_gunlock2:
  	gfs2_glock_dq_uninit(ghs + 1);
194c011fc   Steven Whitehouse   GFS2: Move most o...
727
  fail_gunlock:
f2741d989   Steven Whitehouse   GFS2: Move all lo...
728
  	gfs2_glock_dq_uninit(ghs);
40ac218f5   Steven Whitehouse   GFS2: Fix inode a...
729
730
731
732
  	if (inode && !IS_ERR(inode)) {
  		set_bit(GIF_ALLOC_FAILED, &GFS2_I(inode)->i_flags);
  		iput(inode);
  	}
194c011fc   Steven Whitehouse   GFS2: Move most o...
733
734
735
  fail:
  	if (bh)
  		brelse(bh);
f2741d989   Steven Whitehouse   GFS2: Move all lo...
736
  	return error;
194c011fc   Steven Whitehouse   GFS2: Move most o...
737
  }
f2741d989   Steven Whitehouse   GFS2: Move all lo...
738

194c011fc   Steven Whitehouse   GFS2: Move most o...
739
  /**
b3b94faa5   David Teigland   [GFS2] The core o...
740
741
742
743
744
745
746
747
748
   * gfs2_create - Create a file
   * @dir: The directory in which to create the file
   * @dentry: The dentry of the new file
   * @mode: The mode of the new file
   *
   * Returns: errno
   */
  
  static int gfs2_create(struct inode *dir, struct dentry *dentry,
4acdaf27e   Al Viro   switch ->create()...
749
  		       umode_t mode, struct nameidata *nd)
b3b94faa5   David Teigland   [GFS2] The core o...
750
  {
9a63edd12   Steven Whitehouse   GFS2: Clean up gf...
751
752
753
754
  	int excl = 0;
  	if (nd && (nd->flags & LOOKUP_EXCL))
  		excl = 1;
  	return gfs2_create_inode(dir, dentry, S_IFREG | mode, 0, NULL, 0, excl);
b3b94faa5   David Teigland   [GFS2] The core o...
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
  }
  
  /**
   * gfs2_lookup - Look up a filename in a directory and return its inode
   * @dir: The directory inode
   * @dentry: The dentry of the new inode
   * @nd: passed from Linux VFS, ignored by us
   *
   * Called by the VFS layer. Lock dir and call gfs2_lookupi()
   *
   * Returns: errno
   */
  
  static struct dentry *gfs2_lookup(struct inode *dir, struct dentry *dentry,
  				  struct nameidata *nd)
  {
6c673ab39   Al Viro   simplify gfs2_loo...
771
772
  	struct inode *inode = gfs2_lookupi(dir, &dentry->d_name, 0);
  	if (inode && !IS_ERR(inode)) {
9656b2c14   Steven Whitehouse   [GFS2] Fix proble...
773
774
775
776
777
778
779
780
781
  		struct gfs2_glock *gl = GFS2_I(inode)->i_gl;
  		struct gfs2_holder gh;
  		int error;
  		error = gfs2_glock_nq_init(gl, LM_ST_SHARED, LM_FLAG_ANY, &gh);
  		if (error) {
  			iput(inode);
  			return ERR_PTR(error);
  		}
  		gfs2_glock_dq_uninit(&gh);
9656b2c14   Steven Whitehouse   [GFS2] Fix proble...
782
  	}
6c673ab39   Al Viro   simplify gfs2_loo...
783
  	return d_splice_alias(inode, dentry);
b3b94faa5   David Teigland   [GFS2] The core o...
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
  }
  
  /**
   * gfs2_link - Link to a file
   * @old_dentry: The inode to link
   * @dir: Add link to this directory
   * @dentry: The name of the link
   *
   * Link the inode in "old_dentry" into the directory "dir" with the
   * name in "dentry".
   *
   * Returns: errno
   */
  
  static int gfs2_link(struct dentry *old_dentry, struct inode *dir,
  		     struct dentry *dentry)
  {
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
801
802
  	struct gfs2_inode *dip = GFS2_I(dir);
  	struct gfs2_sbd *sdp = GFS2_SB(dir);
b3b94faa5   David Teigland   [GFS2] The core o...
803
  	struct inode *inode = old_dentry->d_inode;
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
804
  	struct gfs2_inode *ip = GFS2_I(inode);
b3b94faa5   David Teigland   [GFS2] The core o...
805
  	struct gfs2_holder ghs[2];
2baee03fb   Steven Whitehouse   GFS2: Don't use g...
806
  	struct buffer_head *dibh;
b3b94faa5   David Teigland   [GFS2] The core o...
807
808
  	int alloc_required;
  	int error;
b60623c23   Steven Whitehouse   [GFS2] Shrink gfs...
809
  	if (S_ISDIR(inode->i_mode))
b3b94faa5   David Teigland   [GFS2] The core o...
810
811
812
813
  		return -EPERM;
  
  	gfs2_holder_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, ghs);
  	gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + 1);
72dbf4790   Bob Peterson   GFS2: rm on multi...
814
815
816
817
818
  	error = gfs2_glock_nq(ghs); /* parent */
  	if (error)
  		goto out_parent;
  
  	error = gfs2_glock_nq(ghs + 1); /* child */
b3b94faa5   David Teigland   [GFS2] The core o...
819
  	if (error)
72dbf4790   Bob Peterson   GFS2: rm on multi...
820
  		goto out_child;
b3b94faa5   David Teigland   [GFS2] The core o...
821

d192a8e5c   Steven Whitehouse   GFS2: Double chec...
822
823
824
  	error = -ENOENT;
  	if (inode->i_nlink == 0)
  		goto out_gunlock;
10556cb21   Al Viro   ->permission() sa...
825
  	error = gfs2_permission(dir, MAY_WRITE | MAY_EXEC);
b3b94faa5   David Teigland   [GFS2] The core o...
826
827
  	if (error)
  		goto out_gunlock;
dbb7cae2a   Steven Whitehouse   [GFS2] Clean up i...
828
  	error = gfs2_dir_check(dir, &dentry->d_name, NULL);
b3b94faa5   David Teigland   [GFS2] The core o...
829
830
831
832
833
834
835
836
837
838
  	switch (error) {
  	case -ENOENT:
  		break;
  	case 0:
  		error = -EEXIST;
  	default:
  		goto out_gunlock;
  	}
  
  	error = -EINVAL;
4f56110a0   Steven Whitehouse   [GFS2] Shrink gfs...
839
  	if (!dip->i_inode.i_nlink)
b3b94faa5   David Teigland   [GFS2] The core o...
840
841
  		goto out_gunlock;
  	error = -EFBIG;
ad6203f2b   Steven Whitehouse   GFS2: Move "entri...
842
  	if (dip->i_entries == (u32)-1)
b3b94faa5   David Teigland   [GFS2] The core o...
843
844
845
846
847
  		goto out_gunlock;
  	error = -EPERM;
  	if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
  		goto out_gunlock;
  	error = -EINVAL;
4f56110a0   Steven Whitehouse   [GFS2] Shrink gfs...
848
  	if (!ip->i_inode.i_nlink)
b3b94faa5   David Teigland   [GFS2] The core o...
849
850
  		goto out_gunlock;
  	error = -EMLINK;
4f56110a0   Steven Whitehouse   [GFS2] Shrink gfs...
851
  	if (ip->i_inode.i_nlink == (u32)-1)
b3b94faa5   David Teigland   [GFS2] The core o...
852
  		goto out_gunlock;
c752666c1   Steven Whitehouse   [GFS2] Fix bug in...
853
854
  	alloc_required = error = gfs2_diradd_alloc_required(dir, &dentry->d_name);
  	if (error < 0)
b3b94faa5   David Teigland   [GFS2] The core o...
855
  		goto out_gunlock;
c752666c1   Steven Whitehouse   [GFS2] Fix bug in...
856
  	error = 0;
b3b94faa5   David Teigland   [GFS2] The core o...
857
858
  
  	if (alloc_required) {
564e12b11   Bob Peterson   GFS2: decouple qu...
859
860
861
  		struct gfs2_qadata *qa = gfs2_qadata_get(dip);
  
  		if (!qa) {
182fe5abd   Cyrill Gorcunov   [GFS2] possible n...
862
863
864
  			error = -ENOMEM;
  			goto out_gunlock;
  		}
b3b94faa5   David Teigland   [GFS2] The core o...
865

d82661d96   Steven Whitehouse   [GFS2] Streamline...
866
  		error = gfs2_quota_lock_check(dip);
b3b94faa5   David Teigland   [GFS2] The core o...
867
868
  		if (error)
  			goto out_alloc;
564e12b11   Bob Peterson   GFS2: decouple qu...
869
  		error = gfs2_inplace_reserve(dip, sdp->sd_max_dirres);
b3b94faa5   David Teigland   [GFS2] The core o...
870
871
  		if (error)
  			goto out_gunlock_q;
1b50259bc   Steven Whitehouse   [GFS2] Drop log l...
872
  		error = gfs2_trans_begin(sdp, sdp->sd_max_dirres +
54335b1fc   Steven Whitehouse   GFS2: Cache the m...
873
  					 gfs2_rg_blocks(dip) +
b3b94faa5   David Teigland   [GFS2] The core o...
874
875
876
877
878
879
880
881
882
  					 2 * RES_DINODE + RES_STATFS +
  					 RES_QUOTA, 0);
  		if (error)
  			goto out_ipres;
  	} else {
  		error = gfs2_trans_begin(sdp, 2 * RES_DINODE + RES_LEAF, 0);
  		if (error)
  			goto out_ipres;
  	}
2baee03fb   Steven Whitehouse   GFS2: Don't use g...
883
  	error = gfs2_meta_inode_buffer(ip, &dibh);
b3b94faa5   David Teigland   [GFS2] The core o...
884
885
  	if (error)
  		goto out_end_trans;
3d6ecb7d1   Steven Whitehouse   GFS2: When adding...
886
  	error = gfs2_dir_add(dir, &dentry->d_name, ip);
2baee03fb   Steven Whitehouse   GFS2: Don't use g...
887
888
889
890
891
892
  	if (error)
  		goto out_brelse;
  
  	gfs2_trans_add_bh(ip->i_gl, dibh, 1);
  	inc_nlink(&ip->i_inode);
  	ip->i_inode.i_ctime = CURRENT_TIME;
ab9bbda02   Steven Whitehouse   GFS2: Use ->dirty...
893
894
895
  	ihold(inode);
  	d_instantiate(dentry, inode);
  	mark_inode_dirty(inode);
b3b94faa5   David Teigland   [GFS2] The core o...
896

2baee03fb   Steven Whitehouse   GFS2: Don't use g...
897
898
  out_brelse:
  	brelse(dibh);
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
899
  out_end_trans:
b3b94faa5   David Teigland   [GFS2] The core o...
900
  	gfs2_trans_end(sdp);
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
901
  out_ipres:
b3b94faa5   David Teigland   [GFS2] The core o...
902
903
  	if (alloc_required)
  		gfs2_inplace_release(dip);
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
904
  out_gunlock_q:
b3b94faa5   David Teigland   [GFS2] The core o...
905
906
  	if (alloc_required)
  		gfs2_quota_unlock(dip);
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
907
  out_alloc:
b3b94faa5   David Teigland   [GFS2] The core o...
908
  	if (alloc_required)
564e12b11   Bob Peterson   GFS2: decouple qu...
909
  		gfs2_qadata_put(dip);
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
910
  out_gunlock:
72dbf4790   Bob Peterson   GFS2: rm on multi...
911
912
913
914
  	gfs2_glock_dq(ghs + 1);
  out_child:
  	gfs2_glock_dq(ghs);
  out_parent:
b3b94faa5   David Teigland   [GFS2] The core o...
915
916
  	gfs2_holder_uninit(ghs);
  	gfs2_holder_uninit(ghs + 1);
b3b94faa5   David Teigland   [GFS2] The core o...
917
918
  	return error;
  }
87ec21741   Steven Whitehouse   GFS2: Move gfs2_u...
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
  /*
   * gfs2_unlink_ok - check to see that a inode is still in a directory
   * @dip: the directory
   * @name: the name of the file
   * @ip: the inode
   *
   * Assumes that the lock on (at least) @dip is held.
   *
   * Returns: 0 if the parent/child relationship is correct, errno if it isn't
   */
  
  static int gfs2_unlink_ok(struct gfs2_inode *dip, const struct qstr *name,
  			  const struct gfs2_inode *ip)
  {
  	int error;
  
  	if (IS_IMMUTABLE(&ip->i_inode) || IS_APPEND(&ip->i_inode))
  		return -EPERM;
  
  	if ((dip->i_inode.i_mode & S_ISVTX) &&
  	    dip->i_inode.i_uid != current_fsuid() &&
  	    ip->i_inode.i_uid != current_fsuid() && !capable(CAP_FOWNER))
  		return -EPERM;
  
  	if (IS_APPEND(&dip->i_inode))
  		return -EPERM;
10556cb21   Al Viro   ->permission() sa...
945
  	error = gfs2_permission(&dip->i_inode, MAY_WRITE | MAY_EXEC);
87ec21741   Steven Whitehouse   GFS2: Move gfs2_u...
946
947
948
949
950
951
952
953
954
  	if (error)
  		return error;
  
  	error = gfs2_dir_check(&dip->i_inode, name, ip);
  	if (error)
  		return error;
  
  	return 0;
  }
b3b94faa5   David Teigland   [GFS2] The core o...
955
  /**
855d23ce2   Steven Whitehouse   GFS2: Make gfs2_d...
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
   * gfs2_unlink_inode - Removes an inode from its parent dir and unlinks it
   * @dip: The parent directory
   * @name: The name of the entry in the parent directory
   * @bh: The inode buffer for the inode to be removed
   * @inode: The inode to be removed
   *
   * Called with all the locks and in a transaction. This will only be
   * called for a directory after it has been checked to ensure it is empty.
   *
   * Returns: 0 on success, or an error
   */
  
  static int gfs2_unlink_inode(struct gfs2_inode *dip,
  			     const struct dentry *dentry,
  			     struct buffer_head *bh)
  {
  	struct inode *inode = dentry->d_inode;
  	struct gfs2_inode *ip = GFS2_I(inode);
  	int error;
  
  	error = gfs2_dir_del(dip, dentry);
  	if (error)
  		return error;
  
  	ip->i_entries = 0;
  	inode->i_ctime = CURRENT_TIME;
  	if (S_ISDIR(inode->i_mode))
  		clear_nlink(inode);
  	else
  		drop_nlink(inode);
855d23ce2   Steven Whitehouse   GFS2: Make gfs2_d...
986
987
988
989
990
991
992
993
994
995
  	mark_inode_dirty(inode);
  	if (inode->i_nlink == 0)
  		gfs2_unlink_di(inode);
  	return 0;
  }
  
  
  /**
   * gfs2_unlink - Unlink an inode (this does rmdir as well)
   * @dir: The inode of the directory containing the inode to unlink
b3b94faa5   David Teigland   [GFS2] The core o...
996
997
   * @dentry: The file itself
   *
855d23ce2   Steven Whitehouse   GFS2: Make gfs2_d...
998
999
   * This routine uses the type of the inode as a flag to figure out
   * whether this is an unlink or an rmdir.
b3b94faa5   David Teigland   [GFS2] The core o...
1000
1001
1002
1003
1004
1005
   *
   * Returns: errno
   */
  
  static int gfs2_unlink(struct inode *dir, struct dentry *dentry)
  {
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
1006
1007
  	struct gfs2_inode *dip = GFS2_I(dir);
  	struct gfs2_sbd *sdp = GFS2_SB(dir);
855d23ce2   Steven Whitehouse   GFS2: Make gfs2_d...
1008
1009
1010
  	struct inode *inode = dentry->d_inode;
  	struct gfs2_inode *ip = GFS2_I(inode);
  	struct buffer_head *bh;
ddee76089   Russell Cattelan   [GFS2] Fix unlink...
1011
1012
  	struct gfs2_holder ghs[3];
  	struct gfs2_rgrpd *rgd;
87654896c   Steven Whitehouse   GFS2: More automa...
1013
  	int error = -EROFS;
b3b94faa5   David Teigland   [GFS2] The core o...
1014

b3b94faa5   David Teigland   [GFS2] The core o...
1015
  	gfs2_holder_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, ghs);
ddee76089   Russell Cattelan   [GFS2] Fix unlink...
1016
  	gfs2_holder_init(ip->i_gl,  LM_ST_EXCLUSIVE, 0, ghs + 1);
b3b94faa5   David Teigland   [GFS2] The core o...
1017

dbb7cae2a   Steven Whitehouse   [GFS2] Clean up i...
1018
  	rgd = gfs2_blk2rgrpd(sdp, ip->i_no_addr);
87654896c   Steven Whitehouse   GFS2: More automa...
1019
1020
  	if (!rgd)
  		goto out_inodes;
ddee76089   Russell Cattelan   [GFS2] Fix unlink...
1021
  	gfs2_holder_init(rgd->rd_gl, LM_ST_EXCLUSIVE, 0, ghs + 2);
8497a46e1   Steven Whitehouse   [GFS2] Correct lo...
1022
  	error = gfs2_glock_nq(ghs); /* parent */
b3b94faa5   David Teigland   [GFS2] The core o...
1023
  	if (error)
8497a46e1   Steven Whitehouse   [GFS2] Correct lo...
1024
1025
1026
1027
1028
  		goto out_parent;
  
  	error = gfs2_glock_nq(ghs + 1); /* child */
  	if (error)
  		goto out_child;
d192a8e5c   Steven Whitehouse   GFS2: Double chec...
1029
  	error = -ENOENT;
855d23ce2   Steven Whitehouse   GFS2: Make gfs2_d...
1030
  	if (inode->i_nlink == 0)
d192a8e5c   Steven Whitehouse   GFS2: Double chec...
1031
  		goto out_rgrp;
855d23ce2   Steven Whitehouse   GFS2: Make gfs2_d...
1032
1033
1034
1035
1036
  	if (S_ISDIR(inode->i_mode)) {
  		error = -ENOTEMPTY;
  		if (ip->i_entries > 2 || inode->i_nlink > 2)
  			goto out_rgrp;
  	}
8497a46e1   Steven Whitehouse   [GFS2] Correct lo...
1037
1038
1039
  	error = gfs2_glock_nq(ghs + 2); /* rgrp */
  	if (error)
  		goto out_rgrp;
b3b94faa5   David Teigland   [GFS2] The core o...
1040
1041
1042
  
  	error = gfs2_unlink_ok(dip, &dentry->d_name, ip);
  	if (error)
72dbf4790   Bob Peterson   GFS2: rm on multi...
1043
  		goto out_gunlock;
b3b94faa5   David Teigland   [GFS2] The core o...
1044

855d23ce2   Steven Whitehouse   GFS2: Make gfs2_d...
1045
  	error = gfs2_trans_begin(sdp, 2*RES_DINODE + 3*RES_LEAF + RES_RG_BIT, 0);
b3b94faa5   David Teigland   [GFS2] The core o...
1046
  	if (error)
cd0120751   Roel Kluin   GFS2: jumping to ...
1047
  		goto out_gunlock;
b3b94faa5   David Teigland   [GFS2] The core o...
1048

855d23ce2   Steven Whitehouse   GFS2: Make gfs2_d...
1049
1050
1051
  	error = gfs2_meta_inode_buffer(ip, &bh);
  	if (error)
  		goto out_end_trans;
b3b94faa5   David Teigland   [GFS2] The core o...
1052

855d23ce2   Steven Whitehouse   GFS2: Make gfs2_d...
1053
1054
  	error = gfs2_unlink_inode(dip, dentry, bh);
  	brelse(bh);
b3b94faa5   David Teigland   [GFS2] The core o...
1055

feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
1056
1057
  out_end_trans:
  	gfs2_trans_end(sdp);
72dbf4790   Bob Peterson   GFS2: rm on multi...
1058
  out_gunlock:
8497a46e1   Steven Whitehouse   [GFS2] Correct lo...
1059
1060
  	gfs2_glock_dq(ghs + 2);
  out_rgrp:
8497a46e1   Steven Whitehouse   [GFS2] Correct lo...
1061
1062
  	gfs2_glock_dq(ghs + 1);
  out_child:
8497a46e1   Steven Whitehouse   [GFS2] Correct lo...
1063
1064
  	gfs2_glock_dq(ghs);
  out_parent:
87654896c   Steven Whitehouse   GFS2: More automa...
1065
1066
1067
  	gfs2_holder_uninit(ghs + 2);
  out_inodes:
  	gfs2_holder_uninit(ghs + 1);
8497a46e1   Steven Whitehouse   [GFS2] Correct lo...
1068
  	gfs2_holder_uninit(ghs);
b3b94faa5   David Teigland   [GFS2] The core o...
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
  	return error;
  }
  
  /**
   * gfs2_symlink - Create a symlink
   * @dir: The directory to create the symlink in
   * @dentry: The dentry to put the symlink in
   * @symname: The thing which the link points to
   *
   * Returns: errno
   */
  
  static int gfs2_symlink(struct inode *dir, struct dentry *dentry,
  			const char *symname)
  {
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
1084
  	struct gfs2_sbd *sdp = GFS2_SB(dir);
160b4026d   Steven Whitehouse   GFS2: Clean up sy...
1085
  	unsigned int size;
b3b94faa5   David Teigland   [GFS2] The core o...
1086

b3b94faa5   David Teigland   [GFS2] The core o...
1087
1088
1089
  	size = strlen(symname);
  	if (size > sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode) - 1)
  		return -ENAMETOOLONG;
9a63edd12   Steven Whitehouse   GFS2: Clean up gf...
1090
  	return gfs2_create_inode(dir, dentry, S_IFLNK | S_IRWXUGO, 0, symname, size, 0);
b3b94faa5   David Teigland   [GFS2] The core o...
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
  }
  
  /**
   * gfs2_mkdir - Make a directory
   * @dir: The parent directory of the new one
   * @dentry: The dentry of the new directory
   * @mode: The mode of the new directory
   *
   * Returns: errno
   */
18bb1db3e   Al Viro   switch vfs_mkdir(...
1101
  static int gfs2_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
b3b94faa5   David Teigland   [GFS2] The core o...
1102
  {
9a63edd12   Steven Whitehouse   GFS2: Clean up gf...
1103
  	return gfs2_create_inode(dir, dentry, S_IFDIR | mode, 0, NULL, 0, 0);
b3b94faa5   David Teigland   [GFS2] The core o...
1104
1105
1106
  }
  
  /**
b3b94faa5   David Teigland   [GFS2] The core o...
1107
1108
1109
1110
   * gfs2_mknod - Make a special file
   * @dir: The directory in which the special file will reside
   * @dentry: The dentry of the special file
   * @mode: The mode of the special file
f2741d989   Steven Whitehouse   GFS2: Move all lo...
1111
   * @dev: The device specification of the special file
b3b94faa5   David Teigland   [GFS2] The core o...
1112
1113
   *
   */
1a67aafb5   Al Viro   switch ->mknod() ...
1114
  static int gfs2_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
b3b94faa5   David Teigland   [GFS2] The core o...
1115
1116
  		      dev_t dev)
  {
9a63edd12   Steven Whitehouse   GFS2: Clean up gf...
1117
  	return gfs2_create_inode(dir, dentry, mode, dev, NULL, 0, 0);
b3b94faa5   David Teigland   [GFS2] The core o...
1118
  }
0188d6c58   Steven Whitehouse   GFS2: Fix & clean...
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
  /*
   * gfs2_ok_to_move - check if it's ok to move a directory to another directory
   * @this: move this
   * @to: to here
   *
   * Follow @to back to the root and make sure we don't encounter @this
   * Assumes we already hold the rename lock.
   *
   * Returns: errno
   */
  
  static int gfs2_ok_to_move(struct gfs2_inode *this, struct gfs2_inode *to)
  {
  	struct inode *dir = &to->i_inode;
  	struct super_block *sb = dir->i_sb;
  	struct inode *tmp;
0188d6c58   Steven Whitehouse   GFS2: Fix & clean...
1135
  	int error = 0;
0188d6c58   Steven Whitehouse   GFS2: Fix & clean...
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
  	igrab(dir);
  
  	for (;;) {
  		if (dir == &this->i_inode) {
  			error = -EINVAL;
  			break;
  		}
  		if (dir == sb->s_root->d_inode) {
  			error = 0;
  			break;
  		}
8d1235852   Steven Whitehouse   GFS2: Make . and ...
1147
  		tmp = gfs2_lookupi(dir, &gfs2_qdotdot, 1);
0188d6c58   Steven Whitehouse   GFS2: Fix & clean...
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
  		if (IS_ERR(tmp)) {
  			error = PTR_ERR(tmp);
  			break;
  		}
  
  		iput(dir);
  		dir = tmp;
  	}
  
  	iput(dir);
  
  	return error;
  }
b3b94faa5   David Teigland   [GFS2] The core o...
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
  /**
   * gfs2_rename - Rename a file
   * @odir: Parent directory of old file name
   * @odentry: The old dentry of the file
   * @ndir: Parent directory of new file name
   * @ndentry: The new dentry of the file
   *
   * Returns: errno
   */
  
  static int gfs2_rename(struct inode *odir, struct dentry *odentry,
  		       struct inode *ndir, struct dentry *ndentry)
  {
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
1174
1175
1176
  	struct gfs2_inode *odip = GFS2_I(odir);
  	struct gfs2_inode *ndip = GFS2_I(ndir);
  	struct gfs2_inode *ip = GFS2_I(odentry->d_inode);
b3b94faa5   David Teigland   [GFS2] The core o...
1177
  	struct gfs2_inode *nip = NULL;
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
1178
  	struct gfs2_sbd *sdp = GFS2_SB(odir);
8339ee543   Steven Whitehouse   GFS2: Make resour...
1179
  	struct gfs2_holder ghs[5], r_gh = { .gh_gl = NULL, };
ddee76089   Russell Cattelan   [GFS2] Fix unlink...
1180
  	struct gfs2_rgrpd *nrgd;
b3b94faa5   David Teigland   [GFS2] The core o...
1181
1182
  	unsigned int num_gh;
  	int dir_rename = 0;
24b977b5f   Steven Whitehouse   GFS2: Fix locking...
1183
  	int alloc_required = 0;
b3b94faa5   David Teigland   [GFS2] The core o...
1184
1185
  	unsigned int x;
  	int error;
b3b94faa5   David Teigland   [GFS2] The core o...
1186
  	if (ndentry->d_inode) {
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
1187
  		nip = GFS2_I(ndentry->d_inode);
b3b94faa5   David Teigland   [GFS2] The core o...
1188
1189
1190
  		if (ip == nip)
  			return 0;
  	}
0188d6c58   Steven Whitehouse   GFS2: Fix & clean...
1191
1192
1193
  	if (odip != ndip) {
  		error = gfs2_glock_nq_init(sdp->sd_rename_gl, LM_ST_EXCLUSIVE,
  					   0, &r_gh);
b3b94faa5   David Teigland   [GFS2] The core o...
1194
1195
  		if (error)
  			goto out;
0188d6c58   Steven Whitehouse   GFS2: Fix & clean...
1196
1197
1198
1199
1200
1201
1202
  		if (S_ISDIR(ip->i_inode.i_mode)) {
  			dir_rename = 1;
  			/* don't move a dirctory into it's subdir */
  			error = gfs2_ok_to_move(ip, ndip);
  			if (error)
  				goto out_gunlock_r;
  		}
b3b94faa5   David Teigland   [GFS2] The core o...
1203
  	}
d9d1ca305   Steven Whitehouse   [GFS2] Fix double...
1204
  	num_gh = 1;
b3b94faa5   David Teigland   [GFS2] The core o...
1205
  	gfs2_holder_init(odip->i_gl, LM_ST_EXCLUSIVE, 0, ghs);
d9d1ca305   Steven Whitehouse   [GFS2] Fix double...
1206
1207
1208
1209
1210
1211
  	if (odip != ndip) {
  		gfs2_holder_init(ndip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + num_gh);
  		num_gh++;
  	}
  	gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + num_gh);
  	num_gh++;
b3b94faa5   David Teigland   [GFS2] The core o...
1212

d9d1ca305   Steven Whitehouse   [GFS2] Fix double...
1213
1214
1215
  	if (nip) {
  		gfs2_holder_init(nip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + num_gh);
  		num_gh++;
ddee76089   Russell Cattelan   [GFS2] Fix unlink...
1216
1217
1218
1219
  		/* grab the resource lock for unlink flag twiddling 
  		 * this is the case of the target file already existing
  		 * so we unlink before doing the rename
  		 */
dbb7cae2a   Steven Whitehouse   [GFS2] Clean up i...
1220
  		nrgd = gfs2_blk2rgrpd(sdp, nip->i_no_addr);
ddee76089   Russell Cattelan   [GFS2] Fix unlink...
1221
1222
  		if (nrgd)
  			gfs2_holder_init(nrgd->rd_gl, LM_ST_EXCLUSIVE, 0, ghs + num_gh++);
d9d1ca305   Steven Whitehouse   [GFS2] Fix double...
1223
  	}
b3b94faa5   David Teigland   [GFS2] The core o...
1224

72dbf4790   Bob Peterson   GFS2: rm on multi...
1225
1226
1227
1228
1229
  	for (x = 0; x < num_gh; x++) {
  		error = gfs2_glock_nq(ghs + x);
  		if (error)
  			goto out_gunlock;
  	}
b3b94faa5   David Teigland   [GFS2] The core o...
1230

d192a8e5c   Steven Whitehouse   GFS2: Double chec...
1231
1232
1233
  	error = -ENOENT;
  	if (ip->i_inode.i_nlink == 0)
  		goto out_gunlock;
b3b94faa5   David Teigland   [GFS2] The core o...
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
  	/* Check out the old directory */
  
  	error = gfs2_unlink_ok(odip, &odentry->d_name, ip);
  	if (error)
  		goto out_gunlock;
  
  	/* Check out the new directory */
  
  	if (nip) {
  		error = gfs2_unlink_ok(ndip, &ndentry->d_name, nip);
  		if (error)
  			goto out_gunlock;
d192a8e5c   Steven Whitehouse   GFS2: Double chec...
1246
1247
1248
1249
  		if (nip->i_inode.i_nlink == 0) {
  			error = -EAGAIN;
  			goto out_gunlock;
  		}
b60623c23   Steven Whitehouse   [GFS2] Shrink gfs...
1250
  		if (S_ISDIR(nip->i_inode.i_mode)) {
ad6203f2b   Steven Whitehouse   GFS2: Move "entri...
1251
  			if (nip->i_entries < 2) {
94fb763b1   Steven Whitehouse   GFS2: Remove gfs2...
1252
  				gfs2_consist_inode(nip);
b3b94faa5   David Teigland   [GFS2] The core o...
1253
1254
1255
  				error = -EIO;
  				goto out_gunlock;
  			}
ad6203f2b   Steven Whitehouse   GFS2: Move "entri...
1256
  			if (nip->i_entries > 2) {
b3b94faa5   David Teigland   [GFS2] The core o...
1257
1258
1259
1260
1261
  				error = -ENOTEMPTY;
  				goto out_gunlock;
  			}
  		}
  	} else {
10556cb21   Al Viro   ->permission() sa...
1262
  		error = gfs2_permission(ndir, MAY_WRITE | MAY_EXEC);
b3b94faa5   David Teigland   [GFS2] The core o...
1263
1264
  		if (error)
  			goto out_gunlock;
dbb7cae2a   Steven Whitehouse   [GFS2] Clean up i...
1265
  		error = gfs2_dir_check(ndir, &ndentry->d_name, NULL);
b3b94faa5   David Teigland   [GFS2] The core o...
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
  		switch (error) {
  		case -ENOENT:
  			error = 0;
  			break;
  		case 0:
  			error = -EEXIST;
  		default:
  			goto out_gunlock;
  		};
  
  		if (odip != ndip) {
4f56110a0   Steven Whitehouse   [GFS2] Shrink gfs...
1277
  			if (!ndip->i_inode.i_nlink) {
d192a8e5c   Steven Whitehouse   GFS2: Double chec...
1278
  				error = -ENOENT;
b3b94faa5   David Teigland   [GFS2] The core o...
1279
1280
  				goto out_gunlock;
  			}
ad6203f2b   Steven Whitehouse   GFS2: Move "entri...
1281
  			if (ndip->i_entries == (u32)-1) {
b3b94faa5   David Teigland   [GFS2] The core o...
1282
1283
1284
  				error = -EFBIG;
  				goto out_gunlock;
  			}
b60623c23   Steven Whitehouse   [GFS2] Shrink gfs...
1285
  			if (S_ISDIR(ip->i_inode.i_mode) &&
4f56110a0   Steven Whitehouse   [GFS2] Shrink gfs...
1286
  			    ndip->i_inode.i_nlink == (u32)-1) {
b3b94faa5   David Teigland   [GFS2] The core o...
1287
1288
1289
1290
1291
1292
1293
1294
1295
  				error = -EMLINK;
  				goto out_gunlock;
  			}
  		}
  	}
  
  	/* Check out the dir to be renamed */
  
  	if (dir_rename) {
10556cb21   Al Viro   ->permission() sa...
1296
  		error = gfs2_permission(odentry->d_inode, MAY_WRITE);
b3b94faa5   David Teigland   [GFS2] The core o...
1297
1298
1299
  		if (error)
  			goto out_gunlock;
  	}
24b977b5f   Steven Whitehouse   GFS2: Fix locking...
1300
1301
1302
  	if (nip == NULL)
  		alloc_required = gfs2_diradd_alloc_required(ndir, &ndentry->d_name);
  	error = alloc_required;
c752666c1   Steven Whitehouse   [GFS2] Fix bug in...
1303
  	if (error < 0)
b3b94faa5   David Teigland   [GFS2] The core o...
1304
  		goto out_gunlock;
c752666c1   Steven Whitehouse   [GFS2] Fix bug in...
1305
  	error = 0;
b3b94faa5   David Teigland   [GFS2] The core o...
1306
1307
  
  	if (alloc_required) {
564e12b11   Bob Peterson   GFS2: decouple qu...
1308
1309
1310
  		struct gfs2_qadata *qa = gfs2_qadata_get(ndip);
  
  		if (!qa) {
182fe5abd   Cyrill Gorcunov   [GFS2] possible n...
1311
1312
1313
  			error = -ENOMEM;
  			goto out_gunlock;
  		}
b3b94faa5   David Teigland   [GFS2] The core o...
1314

d82661d96   Steven Whitehouse   [GFS2] Streamline...
1315
  		error = gfs2_quota_lock_check(ndip);
b3b94faa5   David Teigland   [GFS2] The core o...
1316
1317
  		if (error)
  			goto out_alloc;
564e12b11   Bob Peterson   GFS2: decouple qu...
1318
  		error = gfs2_inplace_reserve(ndip, sdp->sd_max_dirres);
b3b94faa5   David Teigland   [GFS2] The core o...
1319
1320
  		if (error)
  			goto out_gunlock_q;
fe1bdedc6   Steven Whitehouse   [GFS2] Use vmallo...
1321
  		error = gfs2_trans_begin(sdp, sdp->sd_max_dirres +
54335b1fc   Steven Whitehouse   GFS2: Cache the m...
1322
  					 gfs2_rg_blocks(ndip) +
b3b94faa5   David Teigland   [GFS2] The core o...
1323
  					 4 * RES_DINODE + 4 * RES_LEAF +
87d21e07f   S. Wendy Cheng   [GFS2] Fix gfs2_r...
1324
  					 RES_STATFS + RES_QUOTA + 4, 0);
b3b94faa5   David Teigland   [GFS2] The core o...
1325
1326
1327
1328
  		if (error)
  			goto out_ipreserv;
  	} else {
  		error = gfs2_trans_begin(sdp, 4 * RES_DINODE +
87d21e07f   S. Wendy Cheng   [GFS2] Fix gfs2_r...
1329
  					 5 * RES_LEAF + 4, 0);
b3b94faa5   David Teigland   [GFS2] The core o...
1330
1331
1332
1333
1334
1335
1336
  		if (error)
  			goto out_gunlock;
  	}
  
  	/* Remove the target file, if it exists */
  
  	if (nip) {
855d23ce2   Steven Whitehouse   GFS2: Make gfs2_d...
1337
1338
  		struct buffer_head *bh;
  		error = gfs2_meta_inode_buffer(nip, &bh);
b3b94faa5   David Teigland   [GFS2] The core o...
1339
1340
  		if (error)
  			goto out_end_trans;
855d23ce2   Steven Whitehouse   GFS2: Make gfs2_d...
1341
1342
  		error = gfs2_unlink_inode(ndip, ndentry, bh);
  		brelse(bh);
b3b94faa5   David Teigland   [GFS2] The core o...
1343
1344
1345
  	}
  
  	if (dir_rename) {
8d1235852   Steven Whitehouse   GFS2: Make . and ...
1346
  		error = gfs2_dir_mvino(ip, &gfs2_qdotdot, ndip, DT_DIR);
b3b94faa5   David Teigland   [GFS2] The core o...
1347
1348
1349
1350
1351
1352
1353
  		if (error)
  			goto out_end_trans;
  	} else {
  		struct buffer_head *dibh;
  		error = gfs2_meta_inode_buffer(ip, &dibh);
  		if (error)
  			goto out_end_trans;
4bd91ba18   Steven Whitehouse   [GFS2] Add nanose...
1354
  		ip->i_inode.i_ctime = CURRENT_TIME;
d4e9c4c3b   Steven Whitehouse   [GFS2] Add an add...
1355
  		gfs2_trans_add_bh(ip->i_gl, dibh, 1);
539e5d6b7   Steven Whitehouse   [GFS2] Change arg...
1356
  		gfs2_dinode_out(ip, dibh->b_data);
b3b94faa5   David Teigland   [GFS2] The core o...
1357
1358
  		brelse(dibh);
  	}
855d23ce2   Steven Whitehouse   GFS2: Make gfs2_d...
1359
  	error = gfs2_dir_del(odip, odentry);
b3b94faa5   David Teigland   [GFS2] The core o...
1360
1361
  	if (error)
  		goto out_end_trans;
3d6ecb7d1   Steven Whitehouse   GFS2: When adding...
1362
  	error = gfs2_dir_add(ndir, &ndentry->d_name, ip);
b3b94faa5   David Teigland   [GFS2] The core o...
1363
1364
  	if (error)
  		goto out_end_trans;
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
1365
  out_end_trans:
b3b94faa5   David Teigland   [GFS2] The core o...
1366
  	gfs2_trans_end(sdp);
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
1367
  out_ipreserv:
b3b94faa5   David Teigland   [GFS2] The core o...
1368
1369
  	if (alloc_required)
  		gfs2_inplace_release(ndip);
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
1370
  out_gunlock_q:
b3b94faa5   David Teigland   [GFS2] The core o...
1371
1372
  	if (alloc_required)
  		gfs2_quota_unlock(ndip);
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
1373
  out_alloc:
b3b94faa5   David Teigland   [GFS2] The core o...
1374
  	if (alloc_required)
564e12b11   Bob Peterson   GFS2: decouple qu...
1375
  		gfs2_qadata_put(ndip);
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
1376
  out_gunlock:
72dbf4790   Bob Peterson   GFS2: rm on multi...
1377
1378
  	while (x--) {
  		gfs2_glock_dq(ghs + x);
b3b94faa5   David Teigland   [GFS2] The core o...
1379
  		gfs2_holder_uninit(ghs + x);
72dbf4790   Bob Peterson   GFS2: rm on multi...
1380
  	}
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
1381
  out_gunlock_r:
0188d6c58   Steven Whitehouse   GFS2: Fix & clean...
1382
  	if (r_gh.gh_gl)
b3b94faa5   David Teigland   [GFS2] The core o...
1383
  		gfs2_glock_dq_uninit(&r_gh);
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
1384
  out:
b3b94faa5   David Teigland   [GFS2] The core o...
1385
1386
1387
1388
  	return error;
  }
  
  /**
c177c2ac8   Al Viro   Switch gfs2 to nd...
1389
1390
1391
   * gfs2_follow_link - Follow a symbolic link
   * @dentry: The dentry of the link
   * @nd: Data that we pass to vfs_follow_link()
536baf02f   Steven Whitehouse   GFS2: Move gfs2_r...
1392
   *
c177c2ac8   Al Viro   Switch gfs2 to nd...
1393
   * This can handle symlinks of any size.
536baf02f   Steven Whitehouse   GFS2: Move gfs2_r...
1394
   *
c177c2ac8   Al Viro   Switch gfs2 to nd...
1395
   * Returns: 0 on success or error code
536baf02f   Steven Whitehouse   GFS2: Move gfs2_r...
1396
   */
c177c2ac8   Al Viro   Switch gfs2 to nd...
1397
  static void *gfs2_follow_link(struct dentry *dentry, struct nameidata *nd)
536baf02f   Steven Whitehouse   GFS2: Move gfs2_r...
1398
  {
c177c2ac8   Al Viro   Switch gfs2 to nd...
1399
  	struct gfs2_inode *ip = GFS2_I(dentry->d_inode);
536baf02f   Steven Whitehouse   GFS2: Move gfs2_r...
1400
1401
  	struct gfs2_holder i_gh;
  	struct buffer_head *dibh;
160b4026d   Steven Whitehouse   GFS2: Clean up sy...
1402
  	unsigned int size;
c177c2ac8   Al Viro   Switch gfs2 to nd...
1403
  	char *buf;
536baf02f   Steven Whitehouse   GFS2: Move gfs2_r...
1404
1405
1406
1407
1408
1409
  	int error;
  
  	gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 0, &i_gh);
  	error = gfs2_glock_nq(&i_gh);
  	if (error) {
  		gfs2_holder_uninit(&i_gh);
c177c2ac8   Al Viro   Switch gfs2 to nd...
1410
1411
  		nd_set_link(nd, ERR_PTR(error));
  		return NULL;
536baf02f   Steven Whitehouse   GFS2: Move gfs2_r...
1412
  	}
a2e0f7993   Steven Whitehouse   GFS2: Remove i_di...
1413
1414
  	size = (unsigned int)i_size_read(&ip->i_inode);
  	if (size == 0) {
536baf02f   Steven Whitehouse   GFS2: Move gfs2_r...
1415
  		gfs2_consist_inode(ip);
c177c2ac8   Al Viro   Switch gfs2 to nd...
1416
  		buf = ERR_PTR(-EIO);
536baf02f   Steven Whitehouse   GFS2: Move gfs2_r...
1417
1418
1419
1420
  		goto out;
  	}
  
  	error = gfs2_meta_inode_buffer(ip, &dibh);
c177c2ac8   Al Viro   Switch gfs2 to nd...
1421
1422
  	if (error) {
  		buf = ERR_PTR(error);
536baf02f   Steven Whitehouse   GFS2: Move gfs2_r...
1423
  		goto out;
536baf02f   Steven Whitehouse   GFS2: Move gfs2_r...
1424
  	}
160b4026d   Steven Whitehouse   GFS2: Clean up sy...
1425
  	buf = kzalloc(size + 1, GFP_NOFS);
c177c2ac8   Al Viro   Switch gfs2 to nd...
1426
1427
1428
  	if (!buf)
  		buf = ERR_PTR(-ENOMEM);
  	else
160b4026d   Steven Whitehouse   GFS2: Clean up sy...
1429
  		memcpy(buf, dibh->b_data + sizeof(struct gfs2_dinode), size);
536baf02f   Steven Whitehouse   GFS2: Move gfs2_r...
1430
1431
1432
  	brelse(dibh);
  out:
  	gfs2_glock_dq_uninit(&i_gh);
c177c2ac8   Al Viro   Switch gfs2 to nd...
1433
1434
  	nd_set_link(nd, buf);
  	return NULL;
b3b94faa5   David Teigland   [GFS2] The core o...
1435
  }
c177c2ac8   Al Viro   Switch gfs2 to nd...
1436
  static void gfs2_put_link(struct dentry *dentry, struct nameidata *nd, void *p)
b3b94faa5   David Teigland   [GFS2] The core o...
1437
  {
c177c2ac8   Al Viro   Switch gfs2 to nd...
1438
1439
1440
  	char *s = nd_get_link(nd);
  	if (!IS_ERR(s))
  		kfree(s);
b3b94faa5   David Teigland   [GFS2] The core o...
1441
1442
1443
1444
  }
  
  /**
   * gfs2_permission -
75d5cfbe4   Steven Whitehouse   GFS2: Post-VFS sc...
1445
1446
1447
   * @inode: The inode
   * @mask: The mask to be tested
   * @flags: Indicates whether this is an RCU path walk or not
b3b94faa5   David Teigland   [GFS2] The core o...
1448
   *
300c7d75f   Steven Whitehouse   [GFS2] Fix recurs...
1449
1450
1451
1452
   * This may be called from the VFS directly, or from within GFS2 with the
   * inode locked, so we look to see if the glock is already locked and only
   * lock the glock if its not already been done.
   *
b3b94faa5   David Teigland   [GFS2] The core o...
1453
1454
   * Returns: errno
   */
10556cb21   Al Viro   ->permission() sa...
1455
  int gfs2_permission(struct inode *inode, int mask)
b3b94faa5   David Teigland   [GFS2] The core o...
1456
  {
b74c79e99   Nick Piggin   fs: provide rcu-w...
1457
  	struct gfs2_inode *ip;
b3b94faa5   David Teigland   [GFS2] The core o...
1458
1459
  	struct gfs2_holder i_gh;
  	int error;
300c7d75f   Steven Whitehouse   [GFS2] Fix recurs...
1460
  	int unlock = 0;
b3b94faa5   David Teigland   [GFS2] The core o...
1461

b74c79e99   Nick Piggin   fs: provide rcu-w...
1462
1463
  
  	ip = GFS2_I(inode);
7afd88d91   Steven Whitehouse   [GFS2] Fix a page...
1464
  	if (gfs2_glock_is_locked_by_me(ip->i_gl) == NULL) {
10556cb21   Al Viro   ->permission() sa...
1465
  		if (mask & MAY_NOT_BLOCK)
75d5cfbe4   Steven Whitehouse   GFS2: Post-VFS sc...
1466
  			return -ECHILD;
300c7d75f   Steven Whitehouse   [GFS2] Fix recurs...
1467
1468
1469
1470
1471
  		error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh);
  		if (error)
  			return error;
  		unlock = 1;
  	}
b3b94faa5   David Teigland   [GFS2] The core o...
1472

f58ba8891   Miklos Szeredi   [GFS2] don't call...
1473
1474
1475
  	if ((mask & MAY_WRITE) && IS_IMMUTABLE(inode))
  		error = -EACCES;
  	else
2830ba7f3   Al Viro   ->permission() sa...
1476
  		error = generic_permission(inode, mask);
300c7d75f   Steven Whitehouse   [GFS2] Fix recurs...
1477
  	if (unlock)
b3b94faa5   David Teigland   [GFS2] The core o...
1478
  		gfs2_glock_dq_uninit(&i_gh);
b3b94faa5   David Teigland   [GFS2] The core o...
1479
1480
1481
  
  	return error;
  }
ab9bbda02   Steven Whitehouse   GFS2: Use ->dirty...
1482
  static int __gfs2_setattr_simple(struct inode *inode, struct iattr *attr)
194c011fc   Steven Whitehouse   GFS2: Move most o...
1483
  {
194c011fc   Steven Whitehouse   GFS2: Move most o...
1484
1485
  	setattr_copy(inode, attr);
  	mark_inode_dirty(inode);
194c011fc   Steven Whitehouse   GFS2: Move most o...
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
  	return 0;
  }
  
  /**
   * gfs2_setattr_simple -
   * @ip:
   * @attr:
   *
   * Returns: errno
   */
ab9bbda02   Steven Whitehouse   GFS2: Use ->dirty...
1496
  int gfs2_setattr_simple(struct inode *inode, struct iattr *attr)
194c011fc   Steven Whitehouse   GFS2: Move most o...
1497
1498
1499
1500
  {
  	int error;
  
  	if (current->journal_info)
ab9bbda02   Steven Whitehouse   GFS2: Use ->dirty...
1501
  		return __gfs2_setattr_simple(inode, attr);
194c011fc   Steven Whitehouse   GFS2: Move most o...
1502

ab9bbda02   Steven Whitehouse   GFS2: Use ->dirty...
1503
  	error = gfs2_trans_begin(GFS2_SB(inode), RES_DINODE, 0);
194c011fc   Steven Whitehouse   GFS2: Move most o...
1504
1505
  	if (error)
  		return error;
ab9bbda02   Steven Whitehouse   GFS2: Use ->dirty...
1506
1507
  	error = __gfs2_setattr_simple(inode, attr);
  	gfs2_trans_end(GFS2_SB(inode));
194c011fc   Steven Whitehouse   GFS2: Move most o...
1508
1509
  	return error;
  }
b3b94faa5   David Teigland   [GFS2] The core o...
1510
1511
  static int setattr_chown(struct inode *inode, struct iattr *attr)
  {
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
1512
1513
  	struct gfs2_inode *ip = GFS2_I(inode);
  	struct gfs2_sbd *sdp = GFS2_SB(inode);
cd915493f   Steven Whitehouse   [GFS2] Change all...
1514
  	u32 ouid, ogid, nuid, ngid;
b3b94faa5   David Teigland   [GFS2] The core o...
1515
  	int error;
2933f9254   Steven Whitehouse   [GFS2] Shrink gfs...
1516
1517
  	ouid = inode->i_uid;
  	ogid = inode->i_gid;
b3b94faa5   David Teigland   [GFS2] The core o...
1518
1519
1520
1521
1522
1523
1524
  	nuid = attr->ia_uid;
  	ngid = attr->ia_gid;
  
  	if (!(attr->ia_valid & ATTR_UID) || ouid == nuid)
  		ouid = nuid = NO_QUOTA_CHANGE;
  	if (!(attr->ia_valid & ATTR_GID) || ogid == ngid)
  		ogid = ngid = NO_QUOTA_CHANGE;
564e12b11   Bob Peterson   GFS2: decouple qu...
1525
  	if (!gfs2_qadata_get(ip))
182fe5abd   Cyrill Gorcunov   [GFS2] possible n...
1526
  		return -ENOMEM;
b3b94faa5   David Teigland   [GFS2] The core o...
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
  
  	error = gfs2_quota_lock(ip, nuid, ngid);
  	if (error)
  		goto out_alloc;
  
  	if (ouid != NO_QUOTA_CHANGE || ogid != NO_QUOTA_CHANGE) {
  		error = gfs2_quota_check(ip, nuid, ngid);
  		if (error)
  			goto out_gunlock_q;
  	}
  
  	error = gfs2_trans_begin(sdp, RES_DINODE + 2 * RES_QUOTA, 0);
  	if (error)
  		goto out_gunlock_q;
ab9bbda02   Steven Whitehouse   GFS2: Use ->dirty...
1541
  	error = gfs2_setattr_simple(inode, attr);
b3b94faa5   David Teigland   [GFS2] The core o...
1542
1543
  	if (error)
  		goto out_end_trans;
b3b94faa5   David Teigland   [GFS2] The core o...
1544
  	if (ouid != NO_QUOTA_CHANGE || ogid != NO_QUOTA_CHANGE) {
77658aad2   Steven Whitehouse   [GFS2] Eliminate ...
1545
1546
1547
  		u64 blocks = gfs2_get_inode_blocks(&ip->i_inode);
  		gfs2_quota_change(ip, -blocks, ouid, ogid);
  		gfs2_quota_change(ip, blocks, nuid, ngid);
b3b94faa5   David Teigland   [GFS2] The core o...
1548
  	}
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
1549
  out_end_trans:
b3b94faa5   David Teigland   [GFS2] The core o...
1550
  	gfs2_trans_end(sdp);
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
1551
  out_gunlock_q:
b3b94faa5   David Teigland   [GFS2] The core o...
1552
  	gfs2_quota_unlock(ip);
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
1553
  out_alloc:
564e12b11   Bob Peterson   GFS2: decouple qu...
1554
  	gfs2_qadata_put(ip);
b3b94faa5   David Teigland   [GFS2] The core o...
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
  	return error;
  }
  
  /**
   * gfs2_setattr - Change attributes on an inode
   * @dentry: The dentry which is changing
   * @attr: The structure describing the change
   *
   * The VFS layer wants to change one or more of an inodes attributes.  Write
   * that change out to disk.
   *
   * Returns: errno
   */
  
  static int gfs2_setattr(struct dentry *dentry, struct iattr *attr)
  {
  	struct inode *inode = dentry->d_inode;
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
1572
  	struct gfs2_inode *ip = GFS2_I(inode);
b3b94faa5   David Teigland   [GFS2] The core o...
1573
1574
  	struct gfs2_holder i_gh;
  	int error;
b3b94faa5   David Teigland   [GFS2] The core o...
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
  	error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &i_gh);
  	if (error)
  		return error;
  
  	error = -EPERM;
  	if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
  		goto out;
  
  	error = inode_change_ok(inode, attr);
  	if (error)
  		goto out;
  
  	if (attr->ia_valid & ATTR_SIZE)
ff8f33c8b   Steven Whitehouse   GFS2: New truncat...
1588
  		error = gfs2_setattr_size(inode, attr->ia_size);
b3b94faa5   David Teigland   [GFS2] The core o...
1589
1590
1591
1592
1593
  	else if (attr->ia_valid & (ATTR_UID | ATTR_GID))
  		error = setattr_chown(inode, attr);
  	else if ((attr->ia_valid & ATTR_MODE) && IS_POSIXACL(inode))
  		error = gfs2_acl_chmod(ip, attr);
  	else
ab9bbda02   Steven Whitehouse   GFS2: Use ->dirty...
1594
  		error = gfs2_setattr_simple(inode, attr);
b3b94faa5   David Teigland   [GFS2] The core o...
1595

a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
1596
  out:
b3b94faa5   David Teigland   [GFS2] The core o...
1597
1598
  	if (!error)
  		mark_inode_dirty(inode);
ab9bbda02   Steven Whitehouse   GFS2: Use ->dirty...
1599
  	gfs2_glock_dq_uninit(&i_gh);
b3b94faa5   David Teigland   [GFS2] The core o...
1600
1601
1602
1603
1604
  	return error;
  }
  
  /**
   * gfs2_getattr - Read out an inode's attributes
26c1a5741   Steven Whitehouse   [GFS2] More code ...
1605
   * @mnt: The vfsmount the inode is being accessed from
b3b94faa5   David Teigland   [GFS2] The core o...
1606
1607
1608
   * @dentry: The dentry to stat
   * @stat: The inode's stats
   *
dcf3dd852   Steven Whitehouse   [GFS2] Fix recurs...
1609
1610
1611
1612
1613
1614
   * This may be called from the VFS directly, or from within GFS2 with the
   * inode locked, so we look to see if the glock is already locked and only
   * lock the glock if its not already been done. Note that its the NFS
   * readdirplus operation which causes this to be called (from filldir)
   * with the glock already held.
   *
b3b94faa5   David Teigland   [GFS2] The core o...
1615
1616
1617
1618
1619
1620
1621
   * Returns: errno
   */
  
  static int gfs2_getattr(struct vfsmount *mnt, struct dentry *dentry,
  			struct kstat *stat)
  {
  	struct inode *inode = dentry->d_inode;
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
1622
  	struct gfs2_inode *ip = GFS2_I(inode);
b3b94faa5   David Teigland   [GFS2] The core o...
1623
1624
  	struct gfs2_holder gh;
  	int error;
dcf3dd852   Steven Whitehouse   [GFS2] Fix recurs...
1625
  	int unlock = 0;
b3b94faa5   David Teigland   [GFS2] The core o...
1626

7afd88d91   Steven Whitehouse   [GFS2] Fix a page...
1627
  	if (gfs2_glock_is_locked_by_me(ip->i_gl) == NULL) {
dcf3dd852   Steven Whitehouse   [GFS2] Fix recurs...
1628
1629
1630
1631
  		error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &gh);
  		if (error)
  			return error;
  		unlock = 1;
b3b94faa5   David Teigland   [GFS2] The core o...
1632
  	}
dcf3dd852   Steven Whitehouse   [GFS2] Fix recurs...
1633
  	generic_fillattr(inode, stat);
d7c103d0b   Steven Whitehouse   [GFS2] Fix recurs...
1634
  	if (unlock)
dcf3dd852   Steven Whitehouse   [GFS2] Fix recurs...
1635
1636
1637
  		gfs2_glock_dq_uninit(&gh);
  
  	return 0;
b3b94faa5   David Teigland   [GFS2] The core o...
1638
1639
1640
1641
1642
  }
  
  static int gfs2_setxattr(struct dentry *dentry, const char *name,
  			 const void *data, size_t size, int flags)
  {
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
1643
  	struct inode *inode = dentry->d_inode;
40b78a322   Steven Whitehouse   GFS2: Clean up of...
1644
1645
1646
  	struct gfs2_inode *ip = GFS2_I(inode);
  	struct gfs2_holder gh;
  	int ret;
b3b94faa5   David Teigland   [GFS2] The core o...
1647

40b78a322   Steven Whitehouse   GFS2: Clean up of...
1648
1649
1650
1651
1652
1653
1654
1655
  	gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);
  	ret = gfs2_glock_nq(&gh);
  	if (ret == 0) {
  		ret = generic_setxattr(dentry, name, data, size, flags);
  		gfs2_glock_dq(&gh);
  	}
  	gfs2_holder_uninit(&gh);
  	return ret;
b3b94faa5   David Teigland   [GFS2] The core o...
1656
1657
1658
1659
1660
  }
  
  static ssize_t gfs2_getxattr(struct dentry *dentry, const char *name,
  			     void *data, size_t size)
  {
40b78a322   Steven Whitehouse   GFS2: Clean up of...
1661
1662
1663
1664
  	struct inode *inode = dentry->d_inode;
  	struct gfs2_inode *ip = GFS2_I(inode);
  	struct gfs2_holder gh;
  	int ret;
b3b94faa5   David Teigland   [GFS2] The core o...
1665

40b78a322   Steven Whitehouse   GFS2: Clean up of...
1666
1667
1668
1669
1670
1671
1672
1673
  	gfs2_holder_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &gh);
  	ret = gfs2_glock_nq(&gh);
  	if (ret == 0) {
  		ret = generic_getxattr(dentry, name, data, size);
  		gfs2_glock_dq(&gh);
  	}
  	gfs2_holder_uninit(&gh);
  	return ret;
b3b94faa5   David Teigland   [GFS2] The core o...
1674
1675
1676
1677
  }
  
  static int gfs2_removexattr(struct dentry *dentry, const char *name)
  {
40b78a322   Steven Whitehouse   GFS2: Clean up of...
1678
1679
1680
1681
  	struct inode *inode = dentry->d_inode;
  	struct gfs2_inode *ip = GFS2_I(inode);
  	struct gfs2_holder gh;
  	int ret;
b3b94faa5   David Teigland   [GFS2] The core o...
1682

40b78a322   Steven Whitehouse   GFS2: Clean up of...
1683
1684
1685
1686
1687
1688
1689
1690
  	gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);
  	ret = gfs2_glock_nq(&gh);
  	if (ret == 0) {
  		ret = generic_removexattr(dentry, name);
  		gfs2_glock_dq(&gh);
  	}
  	gfs2_holder_uninit(&gh);
  	return ret;
b3b94faa5   David Teigland   [GFS2] The core o...
1691
  }
e9079cce2   Steven Whitehouse   GFS2: Support for...
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
  static int gfs2_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
  		       u64 start, u64 len)
  {
  	struct gfs2_inode *ip = GFS2_I(inode);
  	struct gfs2_holder gh;
  	int ret;
  
  	ret = fiemap_check_flags(fieinfo, FIEMAP_FLAG_SYNC);
  	if (ret)
  		return ret;
  
  	mutex_lock(&inode->i_mutex);
  
  	ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, 0, &gh);
  	if (ret)
  		goto out;
  
  	if (gfs2_is_stuffed(ip)) {
  		u64 phys = ip->i_no_addr << inode->i_blkbits;
  		u64 size = i_size_read(inode);
  		u32 flags = FIEMAP_EXTENT_LAST|FIEMAP_EXTENT_NOT_ALIGNED|
  			    FIEMAP_EXTENT_DATA_INLINE;
  		phys += sizeof(struct gfs2_dinode);
  		phys += start;
  		if (start + len > size)
  			len = size - start;
  		if (start < size)
  			ret = fiemap_fill_next_extent(fieinfo, start, phys,
  						      len, flags);
  		if (ret == 1)
  			ret = 0;
  	} else {
  		ret = __generic_block_fiemap(inode, fieinfo, start, len,
  					     gfs2_block_map);
  	}
  
  	gfs2_glock_dq_uninit(&gh);
  out:
  	mutex_unlock(&inode->i_mutex);
  	return ret;
  }
92e1d5be9   Arjan van de Ven   [PATCH] mark stru...
1733
  const struct inode_operations gfs2_file_iops = {
e6305c43e   Al Viro   [PATCH] sanitize ...
1734
  	.permission = gfs2_permission,
b3b94faa5   David Teigland   [GFS2] The core o...
1735
1736
1737
1738
1739
1740
  	.setattr = gfs2_setattr,
  	.getattr = gfs2_getattr,
  	.setxattr = gfs2_setxattr,
  	.getxattr = gfs2_getxattr,
  	.listxattr = gfs2_listxattr,
  	.removexattr = gfs2_removexattr,
e9079cce2   Steven Whitehouse   GFS2: Support for...
1741
  	.fiemap = gfs2_fiemap,
4e34e719e   Christoph Hellwig   fs: take the ACL ...
1742
  	.get_acl = gfs2_get_acl,
b3b94faa5   David Teigland   [GFS2] The core o...
1743
  };
92e1d5be9   Arjan van de Ven   [PATCH] mark stru...
1744
  const struct inode_operations gfs2_dir_iops = {
b3b94faa5   David Teigland   [GFS2] The core o...
1745
1746
1747
1748
1749
1750
  	.create = gfs2_create,
  	.lookup = gfs2_lookup,
  	.link = gfs2_link,
  	.unlink = gfs2_unlink,
  	.symlink = gfs2_symlink,
  	.mkdir = gfs2_mkdir,
855d23ce2   Steven Whitehouse   GFS2: Make gfs2_d...
1751
  	.rmdir = gfs2_unlink,
b3b94faa5   David Teigland   [GFS2] The core o...
1752
1753
  	.mknod = gfs2_mknod,
  	.rename = gfs2_rename,
e6305c43e   Al Viro   [PATCH] sanitize ...
1754
  	.permission = gfs2_permission,
b3b94faa5   David Teigland   [GFS2] The core o...
1755
1756
1757
1758
1759
1760
  	.setattr = gfs2_setattr,
  	.getattr = gfs2_getattr,
  	.setxattr = gfs2_setxattr,
  	.getxattr = gfs2_getxattr,
  	.listxattr = gfs2_listxattr,
  	.removexattr = gfs2_removexattr,
e9079cce2   Steven Whitehouse   GFS2: Support for...
1761
  	.fiemap = gfs2_fiemap,
4e34e719e   Christoph Hellwig   fs: take the ACL ...
1762
  	.get_acl = gfs2_get_acl,
b3b94faa5   David Teigland   [GFS2] The core o...
1763
  };
92e1d5be9   Arjan van de Ven   [PATCH] mark stru...
1764
  const struct inode_operations gfs2_symlink_iops = {
c177c2ac8   Al Viro   Switch gfs2 to nd...
1765
  	.readlink = generic_readlink,
b3b94faa5   David Teigland   [GFS2] The core o...
1766
  	.follow_link = gfs2_follow_link,
c177c2ac8   Al Viro   Switch gfs2 to nd...
1767
  	.put_link = gfs2_put_link,
e6305c43e   Al Viro   [PATCH] sanitize ...
1768
  	.permission = gfs2_permission,
b3b94faa5   David Teigland   [GFS2] The core o...
1769
1770
1771
1772
1773
1774
  	.setattr = gfs2_setattr,
  	.getattr = gfs2_getattr,
  	.setxattr = gfs2_setxattr,
  	.getxattr = gfs2_getxattr,
  	.listxattr = gfs2_listxattr,
  	.removexattr = gfs2_removexattr,
e9079cce2   Steven Whitehouse   GFS2: Support for...
1775
  	.fiemap = gfs2_fiemap,
4e34e719e   Christoph Hellwig   fs: take the ACL ...
1776
  	.get_acl = gfs2_get_acl,
b3b94faa5   David Teigland   [GFS2] The core o...
1777
  };