Blame view

fs/gfs2/ops_inode.c 26.5 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
14
15
16
17
  #include <linux/slab.h>
  #include <linux/spinlock.h>
  #include <linux/completion.h>
  #include <linux/buffer_head.h>
  #include <linux/namei.h>
  #include <linux/utsname.h>
  #include <linux/mm.h>
  #include <linux/xattr.h>
  #include <linux/posix_acl.h>
5c676f6d3   Steven Whitehouse   [GFS2] Macros rem...
18
  #include <linux/gfs2_ondisk.h>
71b86f562   Steven Whitehouse   [GFS2] Further up...
19
  #include <linux/crc32.h>
7d308590a   Fabio Massimo Di Nitto   [GFS2] Export lm_...
20
  #include <linux/lm_interface.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
28
29
30
31
32
33
34
  #include "acl.h"
  #include "bmap.h"
  #include "dir.h"
  #include "eaops.h"
  #include "eattr.h"
  #include "glock.h"
  #include "inode.h"
  #include "meta_io.h"
  #include "ops_dentry.h"
  #include "ops_inode.h"
b3b94faa5   David Teigland   [GFS2] The core o...
35
36
37
  #include "quota.h"
  #include "rgrp.h"
  #include "trans.h"
5c676f6d3   Steven Whitehouse   [GFS2] Macros rem...
38
  #include "util.h"
b3b94faa5   David Teigland   [GFS2] The core o...
39
40
41
42
43
44
45
46
47
48
49
50
51
  
  /**
   * 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,
  		       int mode, struct nameidata *nd)
  {
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
52
53
  	struct gfs2_inode *dip = GFS2_I(dir);
  	struct gfs2_sbd *sdp = GFS2_SB(dir);
b3b94faa5   David Teigland   [GFS2] The core o...
54
55
  	struct gfs2_holder ghs[2];
  	struct inode *inode;
b3b94faa5   David Teigland   [GFS2] The core o...
56

b3b94faa5   David Teigland   [GFS2] The core o...
57
58
59
  	gfs2_holder_init(dip->i_gl, 0, 0, ghs);
  
  	for (;;) {
e7f14f4d0   Steven Whitehouse   [GFS2] Shrink gfs...
60
  		inode = gfs2_createi(ghs, &dentry->d_name, S_IFREG | mode, 0);
7359a19cc   Steven Whitehouse   [GFS2] Fix for ro...
61
  		if (!IS_ERR(inode)) {
b3b94faa5   David Teigland   [GFS2] The core o...
62
63
64
65
66
67
  			gfs2_trans_end(sdp);
  			if (dip->i_alloc.al_rgd)
  				gfs2_inplace_release(dip);
  			gfs2_quota_unlock(dip);
  			gfs2_alloc_put(dip);
  			gfs2_glock_dq_uninit_m(2, ghs);
3a8476dda   Steven Whitehouse   [GFS2] Remove deb...
68
  			mark_inode_dirty(inode);
b3b94faa5   David Teigland   [GFS2] The core o...
69
  			break;
7359a19cc   Steven Whitehouse   [GFS2] Fix for ro...
70
  		} else if (PTR_ERR(inode) != -EEXIST ||
b3b94faa5   David Teigland   [GFS2] The core o...
71
72
  			   (nd->intent.open.flags & O_EXCL)) {
  			gfs2_holder_uninit(ghs);
7359a19cc   Steven Whitehouse   [GFS2] Fix for ro...
73
  			return PTR_ERR(inode);
b3b94faa5   David Teigland   [GFS2] The core o...
74
  		}
c752666c1   Steven Whitehouse   [GFS2] Fix bug in...
75
76
77
  		inode = gfs2_lookupi(dir, &dentry->d_name, 0, nd);
  		if (inode) {
  			if (!IS_ERR(inode)) {
c752666c1   Steven Whitehouse   [GFS2] Fix bug in...
78
79
80
81
82
83
  				gfs2_holder_uninit(ghs);
  				break;
  			} else {
  				gfs2_holder_uninit(ghs);
  				return PTR_ERR(inode);
  			}
b3b94faa5   David Teigland   [GFS2] The core o...
84
85
  		}
  	}
b3b94faa5   David Teigland   [GFS2] The core o...
86
  	d_instantiate(dentry, inode);
b3b94faa5   David Teigland   [GFS2] The core o...
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
  
  	return 0;
  }
  
  /**
   * 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)
  {
b3b94faa5   David Teigland   [GFS2] The core o...
105
  	struct inode *inode = NULL;
b3b94faa5   David Teigland   [GFS2] The core o...
106

c752666c1   Steven Whitehouse   [GFS2] Fix bug in...
107
  	dentry->d_op = &gfs2_dops;
b3b94faa5   David Teigland   [GFS2] The core o...
108

c752666c1   Steven Whitehouse   [GFS2] Fix bug in...
109
110
111
  	inode = gfs2_lookupi(dir, &dentry->d_name, 0, nd);
  	if (inode && IS_ERR(inode))
  		return ERR_PTR(PTR_ERR(inode));
b3b94faa5   David Teigland   [GFS2] The core o...
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
  
  	if (inode)
  		return d_splice_alias(inode, dentry);
  	d_add(dentry, inode);
  
  	return NULL;
  }
  
  /**
   * 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...
135
136
  	struct gfs2_inode *dip = GFS2_I(dir);
  	struct gfs2_sbd *sdp = GFS2_SB(dir);
b3b94faa5   David Teigland   [GFS2] The core o...
137
  	struct inode *inode = old_dentry->d_inode;
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
138
  	struct gfs2_inode *ip = GFS2_I(inode);
b3b94faa5   David Teigland   [GFS2] The core o...
139
140
141
  	struct gfs2_holder ghs[2];
  	int alloc_required;
  	int error;
b60623c23   Steven Whitehouse   [GFS2] Shrink gfs...
142
  	if (S_ISDIR(inode->i_mode))
b3b94faa5   David Teigland   [GFS2] The core o...
143
144
145
146
147
148
149
150
  		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);
  
  	error = gfs2_glock_nq_m(2, ghs);
  	if (error)
  		goto out;
faf450ef4   Steven Whitehouse   [GFS2] Remove gfs...
151
  	error = permission(dir, MAY_WRITE | MAY_EXEC, NULL);
b3b94faa5   David Teigland   [GFS2] The core o...
152
153
  	if (error)
  		goto out_gunlock;
dbb7cae2a   Steven Whitehouse   [GFS2] Clean up i...
154
  	error = gfs2_dir_check(dir, &dentry->d_name, NULL);
b3b94faa5   David Teigland   [GFS2] The core o...
155
156
157
158
159
160
161
162
163
164
  	switch (error) {
  	case -ENOENT:
  		break;
  	case 0:
  		error = -EEXIST;
  	default:
  		goto out_gunlock;
  	}
  
  	error = -EINVAL;
4f56110a0   Steven Whitehouse   [GFS2] Shrink gfs...
165
  	if (!dip->i_inode.i_nlink)
b3b94faa5   David Teigland   [GFS2] The core o...
166
167
  		goto out_gunlock;
  	error = -EFBIG;
cd915493f   Steven Whitehouse   [GFS2] Change all...
168
  	if (dip->i_di.di_entries == (u32)-1)
b3b94faa5   David Teigland   [GFS2] The core o...
169
170
171
172
173
  		goto out_gunlock;
  	error = -EPERM;
  	if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
  		goto out_gunlock;
  	error = -EINVAL;
4f56110a0   Steven Whitehouse   [GFS2] Shrink gfs...
174
  	if (!ip->i_inode.i_nlink)
b3b94faa5   David Teigland   [GFS2] The core o...
175
176
  		goto out_gunlock;
  	error = -EMLINK;
4f56110a0   Steven Whitehouse   [GFS2] Shrink gfs...
177
  	if (ip->i_inode.i_nlink == (u32)-1)
b3b94faa5   David Teigland   [GFS2] The core o...
178
  		goto out_gunlock;
c752666c1   Steven Whitehouse   [GFS2] Fix bug in...
179
180
  	alloc_required = error = gfs2_diradd_alloc_required(dir, &dentry->d_name);
  	if (error < 0)
b3b94faa5   David Teigland   [GFS2] The core o...
181
  		goto out_gunlock;
c752666c1   Steven Whitehouse   [GFS2] Fix bug in...
182
  	error = 0;
b3b94faa5   David Teigland   [GFS2] The core o...
183
184
185
186
187
188
189
  
  	if (alloc_required) {
  		struct gfs2_alloc *al = gfs2_alloc_get(dip);
  
  		error = gfs2_quota_lock(dip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
  		if (error)
  			goto out_alloc;
2933f9254   Steven Whitehouse   [GFS2] Shrink gfs...
190
  		error = gfs2_quota_check(dip, dip->i_inode.i_uid, dip->i_inode.i_gid);
b3b94faa5   David Teigland   [GFS2] The core o...
191
192
193
194
195
196
197
198
  		if (error)
  			goto out_gunlock_q;
  
  		al->al_requested = sdp->sd_max_dirres;
  
  		error = gfs2_inplace_reserve(dip);
  		if (error)
  			goto out_gunlock_q;
1b50259bc   Steven Whitehouse   [GFS2] Drop log l...
199
  		error = gfs2_trans_begin(sdp, sdp->sd_max_dirres +
bb8d8a6f5   Steven Whitehouse   [GFS2] Fix sign p...
200
  					 al->al_rgd->rd_length +
b3b94faa5   David Teigland   [GFS2] The core o...
201
202
203
204
205
206
207
208
209
  					 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;
  	}
dbb7cae2a   Steven Whitehouse   [GFS2] Clean up i...
210
  	error = gfs2_dir_add(dir, &dentry->d_name, ip, IF2DT(inode->i_mode));
b3b94faa5   David Teigland   [GFS2] The core o...
211
212
213
214
  	if (error)
  		goto out_end_trans;
  
  	error = gfs2_change_nlink(ip, +1);
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
215
  out_end_trans:
b3b94faa5   David Teigland   [GFS2] The core o...
216
  	gfs2_trans_end(sdp);
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
217
  out_ipres:
b3b94faa5   David Teigland   [GFS2] The core o...
218
219
  	if (alloc_required)
  		gfs2_inplace_release(dip);
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
220
  out_gunlock_q:
b3b94faa5   David Teigland   [GFS2] The core o...
221
222
  	if (alloc_required)
  		gfs2_quota_unlock(dip);
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
223
  out_alloc:
b3b94faa5   David Teigland   [GFS2] The core o...
224
225
  	if (alloc_required)
  		gfs2_alloc_put(dip);
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
226
  out_gunlock:
b3b94faa5   David Teigland   [GFS2] The core o...
227
  	gfs2_glock_dq_m(2, ghs);
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
228
  out:
b3b94faa5   David Teigland   [GFS2] The core o...
229
230
  	gfs2_holder_uninit(ghs);
  	gfs2_holder_uninit(ghs + 1);
b3b94faa5   David Teigland   [GFS2] The core o...
231
  	if (!error) {
29937ac6c   Steven Whitehouse   [GFS2] Fixes to s...
232
  		atomic_inc(&inode->i_count);
b3b94faa5   David Teigland   [GFS2] The core o...
233
234
235
  		d_instantiate(dentry, inode);
  		mark_inode_dirty(inode);
  	}
b3b94faa5   David Teigland   [GFS2] The core o...
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
  	return error;
  }
  
  /**
   * gfs2_unlink - Unlink a file
   * @dir: The inode of the directory containing the file to unlink
   * @dentry: The file itself
   *
   * Unlink a file.  Call gfs2_unlinki()
   *
   * Returns: errno
   */
  
  static int gfs2_unlink(struct inode *dir, struct dentry *dentry)
  {
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
251
252
253
  	struct gfs2_inode *dip = GFS2_I(dir);
  	struct gfs2_sbd *sdp = GFS2_SB(dir);
  	struct gfs2_inode *ip = GFS2_I(dentry->d_inode);
ddee76089   Russell Cattelan   [GFS2] Fix unlink...
254
255
256
  	struct gfs2_holder ghs[3];
  	struct gfs2_rgrpd *rgd;
  	struct gfs2_holder ri_gh;
b3b94faa5   David Teigland   [GFS2] The core o...
257
  	int error;
ddee76089   Russell Cattelan   [GFS2] Fix unlink...
258
259
260
  	error = gfs2_rindex_hold(sdp, &ri_gh);
  	if (error)
  		return error;
b3b94faa5   David Teigland   [GFS2] The core o...
261
  	gfs2_holder_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, ghs);
ddee76089   Russell Cattelan   [GFS2] Fix unlink...
262
  	gfs2_holder_init(ip->i_gl,  LM_ST_EXCLUSIVE, 0, ghs + 1);
b3b94faa5   David Teigland   [GFS2] The core o...
263

dbb7cae2a   Steven Whitehouse   [GFS2] Clean up i...
264
  	rgd = gfs2_blk2rgrpd(sdp, ip->i_no_addr);
ddee76089   Russell Cattelan   [GFS2] Fix unlink...
265
266
267
268
  	gfs2_holder_init(rgd->rd_gl, LM_ST_EXCLUSIVE, 0, ghs + 2);
  
  
  	error = gfs2_glock_nq_m(3, ghs);
b3b94faa5   David Teigland   [GFS2] The core o...
269
270
271
272
273
274
  	if (error)
  		goto out;
  
  	error = gfs2_unlink_ok(dip, &dentry->d_name, ip);
  	if (error)
  		goto out_gunlock;
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
275
  	error = gfs2_trans_begin(sdp, 2*RES_DINODE + RES_LEAF + RES_RG_BIT, 0);
b3b94faa5   David Teigland   [GFS2] The core o...
276
277
  	if (error)
  		goto out_gunlock;
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
278
279
280
  	error = gfs2_dir_del(dip, &dentry->d_name);
          if (error)
                  goto out_end_trans;
b3b94faa5   David Teigland   [GFS2] The core o...
281

feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
282
  	error = gfs2_change_nlink(ip, -1);
b3b94faa5   David Teigland   [GFS2] The core o...
283

feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
284
285
286
  out_end_trans:
  	gfs2_trans_end(sdp);
  out_gunlock:
ddee76089   Russell Cattelan   [GFS2] Fix unlink...
287
  	gfs2_glock_dq_m(3, ghs);
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
288
  out:
b3b94faa5   David Teigland   [GFS2] The core o...
289
290
  	gfs2_holder_uninit(ghs);
  	gfs2_holder_uninit(ghs + 1);
ddee76089   Russell Cattelan   [GFS2] Fix unlink...
291
292
  	gfs2_holder_uninit(ghs + 2);
  	gfs2_glock_dq_uninit(&ri_gh);
b3b94faa5   David Teigland   [GFS2] The core o...
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
  	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...
308
309
  	struct gfs2_inode *dip = GFS2_I(dir), *ip;
  	struct gfs2_sbd *sdp = GFS2_SB(dir);
b3b94faa5   David Teigland   [GFS2] The core o...
310
311
312
313
314
  	struct gfs2_holder ghs[2];
  	struct inode *inode;
  	struct buffer_head *dibh;
  	int size;
  	int error;
b3b94faa5   David Teigland   [GFS2] The core o...
315
316
317
318
319
320
  	/* Must be stuffed with a null terminator for gfs2_follow_link() */
  	size = strlen(symname);
  	if (size > sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode) - 1)
  		return -ENAMETOOLONG;
  
  	gfs2_holder_init(dip->i_gl, 0, 0, ghs);
e7f14f4d0   Steven Whitehouse   [GFS2] Shrink gfs...
321
  	inode = gfs2_createi(ghs, &dentry->d_name, S_IFLNK | S_IRWXUGO, 0);
7359a19cc   Steven Whitehouse   [GFS2] Fix for ro...
322
  	if (IS_ERR(inode)) {
b3b94faa5   David Teigland   [GFS2] The core o...
323
  		gfs2_holder_uninit(ghs);
7359a19cc   Steven Whitehouse   [GFS2] Fix for ro...
324
  		return PTR_ERR(inode);
b3b94faa5   David Teigland   [GFS2] The core o...
325
  	}
5c676f6d3   Steven Whitehouse   [GFS2] Macros rem...
326
  	ip = ghs[1].gh_gl->gl_object;
b3b94faa5   David Teigland   [GFS2] The core o...
327
328
329
330
331
332
  
  	ip->i_di.di_size = size;
  
  	error = gfs2_meta_inode_buffer(ip, &dibh);
  
  	if (!gfs2_assert_withdraw(sdp, !error)) {
539e5d6b7   Steven Whitehouse   [GFS2] Change arg...
333
  		gfs2_dinode_out(ip, dibh->b_data);
b3b94faa5   David Teigland   [GFS2] The core o...
334
335
336
337
338
339
340
341
342
343
344
345
  		memcpy(dibh->b_data + sizeof(struct gfs2_dinode), symname,
  		       size);
  		brelse(dibh);
  	}
  
  	gfs2_trans_end(sdp);
  	if (dip->i_alloc.al_rgd)
  		gfs2_inplace_release(dip);
  	gfs2_quota_unlock(dip);
  	gfs2_alloc_put(dip);
  
  	gfs2_glock_dq_uninit_m(2, ghs);
b3b94faa5   David Teigland   [GFS2] The core o...
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
  	d_instantiate(dentry, inode);
  	mark_inode_dirty(inode);
  
  	return 0;
  }
  
  /**
   * 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
   */
  
  static int gfs2_mkdir(struct inode *dir, struct dentry *dentry, int mode)
  {
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
363
364
  	struct gfs2_inode *dip = GFS2_I(dir), *ip;
  	struct gfs2_sbd *sdp = GFS2_SB(dir);
b3b94faa5   David Teigland   [GFS2] The core o...
365
366
367
368
  	struct gfs2_holder ghs[2];
  	struct inode *inode;
  	struct buffer_head *dibh;
  	int error;
b3b94faa5   David Teigland   [GFS2] The core o...
369
  	gfs2_holder_init(dip->i_gl, 0, 0, ghs);
e7f14f4d0   Steven Whitehouse   [GFS2] Shrink gfs...
370
  	inode = gfs2_createi(ghs, &dentry->d_name, S_IFDIR | mode, 0);
7359a19cc   Steven Whitehouse   [GFS2] Fix for ro...
371
  	if (IS_ERR(inode)) {
b3b94faa5   David Teigland   [GFS2] The core o...
372
  		gfs2_holder_uninit(ghs);
7359a19cc   Steven Whitehouse   [GFS2] Fix for ro...
373
  		return PTR_ERR(inode);
b3b94faa5   David Teigland   [GFS2] The core o...
374
  	}
5c676f6d3   Steven Whitehouse   [GFS2] Macros rem...
375
  	ip = ghs[1].gh_gl->gl_object;
b3b94faa5   David Teigland   [GFS2] The core o...
376

4f56110a0   Steven Whitehouse   [GFS2] Shrink gfs...
377
  	ip->i_inode.i_nlink = 2;
b3b94faa5   David Teigland   [GFS2] The core o...
378
379
  	ip->i_di.di_size = sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode);
  	ip->i_di.di_flags |= GFS2_DIF_JDATA;
b3b94faa5   David Teigland   [GFS2] The core o...
380
381
382
383
384
385
  	ip->i_di.di_entries = 2;
  
  	error = gfs2_meta_inode_buffer(ip, &dibh);
  
  	if (!gfs2_assert_withdraw(sdp, !error)) {
  		struct gfs2_dinode *di = (struct gfs2_dinode *)dibh->b_data;
c752666c1   Steven Whitehouse   [GFS2] Fix bug in...
386
  		struct gfs2_dirent *dent = (struct gfs2_dirent *)(di+1);
71b86f562   Steven Whitehouse   [GFS2] Further up...
387
  		struct qstr str;
b3b94faa5   David Teigland   [GFS2] The core o...
388

71b86f562   Steven Whitehouse   [GFS2] Further up...
389
  		gfs2_str2qstr(&str, ".");
c752666c1   Steven Whitehouse   [GFS2] Fix bug in...
390
391
  		gfs2_trans_add_bh(ip->i_gl, dibh, 1);
  		gfs2_qstr2dirent(&str, GFS2_DIRENT_SIZE(str.len), dent);
b3b94faa5   David Teigland   [GFS2] The core o...
392
  		dent->de_inum = di->di_num; /* already GFS2 endian */
7ecdb70a0   Steven Whitehouse   [GFS2] Fix endian...
393
  		dent->de_type = cpu_to_be16(DT_DIR);
b3b94faa5   David Teigland   [GFS2] The core o...
394
  		di->di_entries = cpu_to_be32(1);
71b86f562   Steven Whitehouse   [GFS2] Further up...
395
  		gfs2_str2qstr(&str, "..");
c752666c1   Steven Whitehouse   [GFS2] Fix bug in...
396
397
  		dent = (struct gfs2_dirent *)((char*)dent + GFS2_DIRENT_SIZE(1));
  		gfs2_qstr2dirent(&str, dibh->b_size - GFS2_DIRENT_SIZE(1) - sizeof(struct gfs2_dinode), dent);
b3b94faa5   David Teigland   [GFS2] The core o...
398

dbb7cae2a   Steven Whitehouse   [GFS2] Clean up i...
399
  		gfs2_inum_out(dip, dent);
7ecdb70a0   Steven Whitehouse   [GFS2] Fix endian...
400
  		dent->de_type = cpu_to_be16(DT_DIR);
b3b94faa5   David Teigland   [GFS2] The core o...
401

539e5d6b7   Steven Whitehouse   [GFS2] Change arg...
402
  		gfs2_dinode_out(ip, di);
b3b94faa5   David Teigland   [GFS2] The core o...
403
404
405
406
407
408
409
410
411
412
413
414
415
416
  
  		brelse(dibh);
  	}
  
  	error = gfs2_change_nlink(dip, +1);
  	gfs2_assert_withdraw(sdp, !error); /* dip already pinned */
  
  	gfs2_trans_end(sdp);
  	if (dip->i_alloc.al_rgd)
  		gfs2_inplace_release(dip);
  	gfs2_quota_unlock(dip);
  	gfs2_alloc_put(dip);
  
  	gfs2_glock_dq_uninit_m(2, ghs);
b3b94faa5   David Teigland   [GFS2] The core o...
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
  	d_instantiate(dentry, inode);
  	mark_inode_dirty(inode);
  
  	return 0;
  }
  
  /**
   * gfs2_rmdir - Remove a directory
   * @dir: The parent directory of the directory to be removed
   * @dentry: The dentry of the directory to remove
   *
   * Remove a directory. Call gfs2_rmdiri()
   *
   * Returns: errno
   */
  
  static int gfs2_rmdir(struct inode *dir, struct dentry *dentry)
  {
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
435
436
437
  	struct gfs2_inode *dip = GFS2_I(dir);
  	struct gfs2_sbd *sdp = GFS2_SB(dir);
  	struct gfs2_inode *ip = GFS2_I(dentry->d_inode);
ddee76089   Russell Cattelan   [GFS2] Fix unlink...
438
439
440
  	struct gfs2_holder ghs[3];
  	struct gfs2_rgrpd *rgd;
  	struct gfs2_holder ri_gh;
b3b94faa5   David Teigland   [GFS2] The core o...
441
  	int error;
ddee76089   Russell Cattelan   [GFS2] Fix unlink...
442
443
444
445
  
  	error = gfs2_rindex_hold(sdp, &ri_gh);
  	if (error)
  		return error;
b3b94faa5   David Teigland   [GFS2] The core o...
446
447
  	gfs2_holder_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, ghs);
  	gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + 1);
dbb7cae2a   Steven Whitehouse   [GFS2] Clean up i...
448
  	rgd = gfs2_blk2rgrpd(sdp, ip->i_no_addr);
ddee76089   Russell Cattelan   [GFS2] Fix unlink...
449
450
451
  	gfs2_holder_init(rgd->rd_gl, LM_ST_EXCLUSIVE, 0, ghs + 2);
  
  	error = gfs2_glock_nq_m(3, ghs);
b3b94faa5   David Teigland   [GFS2] The core o...
452
453
454
455
456
457
458
459
460
  	if (error)
  		goto out;
  
  	error = gfs2_unlink_ok(dip, &dentry->d_name, ip);
  	if (error)
  		goto out_gunlock;
  
  	if (ip->i_di.di_entries < 2) {
  		if (gfs2_consist_inode(ip))
4cc14f0b8   Steven Whitehouse   [GFS2] Change arg...
461
  			gfs2_dinode_print(ip);
b3b94faa5   David Teigland   [GFS2] The core o...
462
463
464
465
466
467
468
  		error = -EIO;
  		goto out_gunlock;
  	}
  	if (ip->i_di.di_entries > 2) {
  		error = -ENOTEMPTY;
  		goto out_gunlock;
  	}
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
469
  	error = gfs2_trans_begin(sdp, 2 * RES_DINODE + 3 * RES_LEAF + RES_RG_BIT, 0);
b3b94faa5   David Teigland   [GFS2] The core o...
470
471
  	if (error)
  		goto out_gunlock;
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
472
  	error = gfs2_rmdiri(dip, &dentry->d_name, ip);
b3b94faa5   David Teigland   [GFS2] The core o...
473
474
  
  	gfs2_trans_end(sdp);
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
475
  out_gunlock:
ddee76089   Russell Cattelan   [GFS2] Fix unlink...
476
  	gfs2_glock_dq_m(3, ghs);
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
477
  out:
b3b94faa5   David Teigland   [GFS2] The core o...
478
479
  	gfs2_holder_uninit(ghs);
  	gfs2_holder_uninit(ghs + 1);
ddee76089   Russell Cattelan   [GFS2] Fix unlink...
480
481
  	gfs2_holder_uninit(ghs + 2);
  	gfs2_glock_dq_uninit(&ri_gh);
b3b94faa5   David Teigland   [GFS2] The core o...
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
  	return error;
  }
  
  /**
   * 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
   * @rdev: The device specification of the special file
   *
   */
  
  static int gfs2_mknod(struct inode *dir, struct dentry *dentry, int mode,
  		      dev_t dev)
  {
e7f14f4d0   Steven Whitehouse   [GFS2] Shrink gfs...
497
  	struct gfs2_inode *dip = GFS2_I(dir);
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
498
  	struct gfs2_sbd *sdp = GFS2_SB(dir);
b3b94faa5   David Teigland   [GFS2] The core o...
499
500
  	struct gfs2_holder ghs[2];
  	struct inode *inode;
b3b94faa5   David Teigland   [GFS2] The core o...
501
502
  
  	gfs2_holder_init(dip->i_gl, 0, 0, ghs);
e7f14f4d0   Steven Whitehouse   [GFS2] Shrink gfs...
503
  	inode = gfs2_createi(ghs, &dentry->d_name, mode, dev);
7359a19cc   Steven Whitehouse   [GFS2] Fix for ro...
504
  	if (IS_ERR(inode)) {
b3b94faa5   David Teigland   [GFS2] The core o...
505
  		gfs2_holder_uninit(ghs);
7359a19cc   Steven Whitehouse   [GFS2] Fix for ro...
506
  		return PTR_ERR(inode);
b3b94faa5   David Teigland   [GFS2] The core o...
507
  	}
b3b94faa5   David Teigland   [GFS2] The core o...
508
509
510
511
512
513
514
  	gfs2_trans_end(sdp);
  	if (dip->i_alloc.al_rgd)
  		gfs2_inplace_release(dip);
  	gfs2_quota_unlock(dip);
  	gfs2_alloc_put(dip);
  
  	gfs2_glock_dq_uninit_m(2, ghs);
b3b94faa5   David Teigland   [GFS2] The core o...
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
  	d_instantiate(dentry, inode);
  	mark_inode_dirty(inode);
  
  	return 0;
  }
  
  /**
   * 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...
534
535
536
  	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...
537
  	struct gfs2_inode *nip = NULL;
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
538
  	struct gfs2_sbd *sdp = GFS2_SB(odir);
ddee76089   Russell Cattelan   [GFS2] Fix unlink...
539
540
  	struct gfs2_holder ghs[5], r_gh;
  	struct gfs2_rgrpd *nrgd;
b3b94faa5   David Teigland   [GFS2] The core o...
541
542
543
544
545
  	unsigned int num_gh;
  	int dir_rename = 0;
  	int alloc_required;
  	unsigned int x;
  	int error;
b3b94faa5   David Teigland   [GFS2] The core o...
546
  	if (ndentry->d_inode) {
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
547
  		nip = GFS2_I(ndentry->d_inode);
b3b94faa5   David Teigland   [GFS2] The core o...
548
549
550
  		if (ip == nip)
  			return 0;
  	}
b3b94faa5   David Teigland   [GFS2] The core o...
551
  	/* Make sure we aren't trying to move a dirctory into it's subdir */
b60623c23   Steven Whitehouse   [GFS2] Shrink gfs...
552
  	if (S_ISDIR(ip->i_inode.i_mode) && odip != ndip) {
b3b94faa5   David Teigland   [GFS2] The core o...
553
  		dir_rename = 1;
b60623c23   Steven Whitehouse   [GFS2] Shrink gfs...
554
  		error = gfs2_glock_nq_init(sdp->sd_rename_gl, LM_ST_EXCLUSIVE, 0,
b3b94faa5   David Teigland   [GFS2] The core o...
555
556
557
558
559
560
561
562
  					   &r_gh);
  		if (error)
  			goto out;
  
  		error = gfs2_ok_to_move(ip, ndip);
  		if (error)
  			goto out_gunlock_r;
  	}
d9d1ca305   Steven Whitehouse   [GFS2] Fix double...
563
  	num_gh = 1;
b3b94faa5   David Teigland   [GFS2] The core o...
564
  	gfs2_holder_init(odip->i_gl, LM_ST_EXCLUSIVE, 0, ghs);
d9d1ca305   Steven Whitehouse   [GFS2] Fix double...
565
566
567
568
569
570
  	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...
571

d9d1ca305   Steven Whitehouse   [GFS2] Fix double...
572
573
574
  	if (nip) {
  		gfs2_holder_init(nip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + num_gh);
  		num_gh++;
ddee76089   Russell Cattelan   [GFS2] Fix unlink...
575
576
577
578
  		/* 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...
579
  		nrgd = gfs2_blk2rgrpd(sdp, nip->i_no_addr);
ddee76089   Russell Cattelan   [GFS2] Fix unlink...
580
581
  		if (nrgd)
  			gfs2_holder_init(nrgd->rd_gl, LM_ST_EXCLUSIVE, 0, ghs + num_gh++);
d9d1ca305   Steven Whitehouse   [GFS2] Fix double...
582
  	}
b3b94faa5   David Teigland   [GFS2] The core o...
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
  
  	error = gfs2_glock_nq_m(num_gh, ghs);
  	if (error)
  		goto out_uninit;
  
  	/* 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;
b60623c23   Steven Whitehouse   [GFS2] Shrink gfs...
600
  		if (S_ISDIR(nip->i_inode.i_mode)) {
b3b94faa5   David Teigland   [GFS2] The core o...
601
602
  			if (nip->i_di.di_entries < 2) {
  				if (gfs2_consist_inode(nip))
4cc14f0b8   Steven Whitehouse   [GFS2] Change arg...
603
  					gfs2_dinode_print(nip);
b3b94faa5   David Teigland   [GFS2] The core o...
604
605
606
607
608
609
610
611
612
  				error = -EIO;
  				goto out_gunlock;
  			}
  			if (nip->i_di.di_entries > 2) {
  				error = -ENOTEMPTY;
  				goto out_gunlock;
  			}
  		}
  	} else {
faf450ef4   Steven Whitehouse   [GFS2] Remove gfs...
613
  		error = permission(ndir, MAY_WRITE | MAY_EXEC, NULL);
b3b94faa5   David Teigland   [GFS2] The core o...
614
615
  		if (error)
  			goto out_gunlock;
dbb7cae2a   Steven Whitehouse   [GFS2] Clean up i...
616
  		error = gfs2_dir_check(ndir, &ndentry->d_name, NULL);
b3b94faa5   David Teigland   [GFS2] The core o...
617
618
619
620
621
622
623
624
625
626
627
  		switch (error) {
  		case -ENOENT:
  			error = 0;
  			break;
  		case 0:
  			error = -EEXIST;
  		default:
  			goto out_gunlock;
  		};
  
  		if (odip != ndip) {
4f56110a0   Steven Whitehouse   [GFS2] Shrink gfs...
628
  			if (!ndip->i_inode.i_nlink) {
b3b94faa5   David Teigland   [GFS2] The core o...
629
630
631
  				error = -EINVAL;
  				goto out_gunlock;
  			}
cd915493f   Steven Whitehouse   [GFS2] Change all...
632
  			if (ndip->i_di.di_entries == (u32)-1) {
b3b94faa5   David Teigland   [GFS2] The core o...
633
634
635
  				error = -EFBIG;
  				goto out_gunlock;
  			}
b60623c23   Steven Whitehouse   [GFS2] Shrink gfs...
636
  			if (S_ISDIR(ip->i_inode.i_mode) &&
4f56110a0   Steven Whitehouse   [GFS2] Shrink gfs...
637
  			    ndip->i_inode.i_nlink == (u32)-1) {
b3b94faa5   David Teigland   [GFS2] The core o...
638
639
640
641
642
643
644
645
646
  				error = -EMLINK;
  				goto out_gunlock;
  			}
  		}
  	}
  
  	/* Check out the dir to be renamed */
  
  	if (dir_rename) {
faf450ef4   Steven Whitehouse   [GFS2] Remove gfs...
647
  		error = permission(odentry->d_inode, MAY_WRITE, NULL);
b3b94faa5   David Teigland   [GFS2] The core o...
648
649
650
  		if (error)
  			goto out_gunlock;
  	}
c752666c1   Steven Whitehouse   [GFS2] Fix bug in...
651
652
  	alloc_required = error = gfs2_diradd_alloc_required(ndir, &ndentry->d_name);
  	if (error < 0)
b3b94faa5   David Teigland   [GFS2] The core o...
653
  		goto out_gunlock;
c752666c1   Steven Whitehouse   [GFS2] Fix bug in...
654
  	error = 0;
b3b94faa5   David Teigland   [GFS2] The core o...
655
656
657
658
659
660
661
  
  	if (alloc_required) {
  		struct gfs2_alloc *al = gfs2_alloc_get(ndip);
  
  		error = gfs2_quota_lock(ndip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
  		if (error)
  			goto out_alloc;
2933f9254   Steven Whitehouse   [GFS2] Shrink gfs...
662
  		error = gfs2_quota_check(ndip, ndip->i_inode.i_uid, ndip->i_inode.i_gid);
b3b94faa5   David Teigland   [GFS2] The core o...
663
664
665
666
667
668
669
670
  		if (error)
  			goto out_gunlock_q;
  
  		al->al_requested = sdp->sd_max_dirres;
  
  		error = gfs2_inplace_reserve(ndip);
  		if (error)
  			goto out_gunlock_q;
fe1bdedc6   Steven Whitehouse   [GFS2] Use vmallo...
671
  		error = gfs2_trans_begin(sdp, sdp->sd_max_dirres +
bb8d8a6f5   Steven Whitehouse   [GFS2] Fix sign p...
672
  					 al->al_rgd->rd_length +
b3b94faa5   David Teigland   [GFS2] The core o...
673
  					 4 * RES_DINODE + 4 * RES_LEAF +
87d21e07f   S. Wendy Cheng   [GFS2] Fix gfs2_r...
674
  					 RES_STATFS + RES_QUOTA + 4, 0);
b3b94faa5   David Teigland   [GFS2] The core o...
675
676
677
678
  		if (error)
  			goto out_ipreserv;
  	} else {
  		error = gfs2_trans_begin(sdp, 4 * RES_DINODE +
87d21e07f   S. Wendy Cheng   [GFS2] Fix gfs2_r...
679
  					 5 * RES_LEAF + 4, 0);
b3b94faa5   David Teigland   [GFS2] The core o...
680
681
682
683
684
685
686
  		if (error)
  			goto out_gunlock;
  	}
  
  	/* Remove the target file, if it exists */
  
  	if (nip) {
b60623c23   Steven Whitehouse   [GFS2] Shrink gfs...
687
  		if (S_ISDIR(nip->i_inode.i_mode))
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
688
689
690
691
692
  			error = gfs2_rmdiri(ndip, &ndentry->d_name, nip);
  		else {
  			error = gfs2_dir_del(ndip, &ndentry->d_name);
  			if (error)
  				goto out_end_trans;
87d21e07f   S. Wendy Cheng   [GFS2] Fix gfs2_r...
693
  			error = gfs2_change_nlink(nip, -1);
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
694
  		}
b3b94faa5   David Teigland   [GFS2] The core o...
695
696
697
698
699
700
  		if (error)
  			goto out_end_trans;
  	}
  
  	if (dir_rename) {
  		struct qstr name;
71b86f562   Steven Whitehouse   [GFS2] Further up...
701
  		gfs2_str2qstr(&name, "..");
b3b94faa5   David Teigland   [GFS2] The core o...
702
703
704
705
706
707
708
  
  		error = gfs2_change_nlink(ndip, +1);
  		if (error)
  			goto out_end_trans;
  		error = gfs2_change_nlink(odip, -1);
  		if (error)
  			goto out_end_trans;
ffed8ab34   Steven Whitehouse   [GFS2] Fix typo i...
709
  		error = gfs2_dir_mvino(ip, &name, ndip, DT_DIR);
b3b94faa5   David Teigland   [GFS2] The core o...
710
711
712
713
714
715
716
  		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...
717
  		ip->i_inode.i_ctime = CURRENT_TIME;
d4e9c4c3b   Steven Whitehouse   [GFS2] Add an add...
718
  		gfs2_trans_add_bh(ip->i_gl, dibh, 1);
539e5d6b7   Steven Whitehouse   [GFS2] Change arg...
719
  		gfs2_dinode_out(ip, dibh->b_data);
b3b94faa5   David Teigland   [GFS2] The core o...
720
721
722
723
724
725
  		brelse(dibh);
  	}
  
  	error = gfs2_dir_del(odip, &odentry->d_name);
  	if (error)
  		goto out_end_trans;
dbb7cae2a   Steven Whitehouse   [GFS2] Clean up i...
726
  	error = gfs2_dir_add(ndir, &ndentry->d_name, ip, IF2DT(ip->i_inode.i_mode));
b3b94faa5   David Teigland   [GFS2] The core o...
727
728
  	if (error)
  		goto out_end_trans;
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
729
  out_end_trans:
b3b94faa5   David Teigland   [GFS2] The core o...
730
  	gfs2_trans_end(sdp);
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
731
  out_ipreserv:
b3b94faa5   David Teigland   [GFS2] The core o...
732
733
  	if (alloc_required)
  		gfs2_inplace_release(ndip);
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
734
  out_gunlock_q:
b3b94faa5   David Teigland   [GFS2] The core o...
735
736
  	if (alloc_required)
  		gfs2_quota_unlock(ndip);
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
737
  out_alloc:
b3b94faa5   David Teigland   [GFS2] The core o...
738
739
  	if (alloc_required)
  		gfs2_alloc_put(ndip);
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
740
  out_gunlock:
b3b94faa5   David Teigland   [GFS2] The core o...
741
  	gfs2_glock_dq_m(num_gh, ghs);
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
742
  out_uninit:
b3b94faa5   David Teigland   [GFS2] The core o...
743
744
  	for (x = 0; x < num_gh; x++)
  		gfs2_holder_uninit(ghs + x);
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
745
  out_gunlock_r:
b3b94faa5   David Teigland   [GFS2] The core o...
746
747
  	if (dir_rename)
  		gfs2_glock_dq_uninit(&r_gh);
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
748
  out:
b3b94faa5   David Teigland   [GFS2] The core o...
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
  	return error;
  }
  
  /**
   * gfs2_readlink - Read the value of a symlink
   * @dentry: the symlink
   * @buf: the buffer to read the symlink data into
   * @size: the size of the buffer
   *
   * Returns: errno
   */
  
  static int gfs2_readlink(struct dentry *dentry, char __user *user_buf,
  			 int user_size)
  {
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
764
  	struct gfs2_inode *ip = GFS2_I(dentry->d_inode);
b3b94faa5   David Teigland   [GFS2] The core o...
765
766
767
  	char array[GFS2_FAST_NAME_SIZE], *buf = array;
  	unsigned int len = GFS2_FAST_NAME_SIZE;
  	int error;
b3b94faa5   David Teigland   [GFS2] The core o...
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
  	error = gfs2_readlinki(ip, &buf, &len);
  	if (error)
  		return error;
  
  	if (user_size > len - 1)
  		user_size = len - 1;
  
  	if (copy_to_user(user_buf, buf, user_size))
  		error = -EFAULT;
  	else
  		error = user_size;
  
  	if (buf != array)
  		kfree(buf);
  
  	return error;
  }
  
  /**
   * gfs2_follow_link - Follow a symbolic link
   * @dentry: The dentry of the link
   * @nd: Data that we pass to vfs_follow_link()
   *
   * This can handle symlinks of any size. It is optimised for symlinks
   * under GFS2_FAST_NAME_SIZE.
   *
   * Returns: 0 on success or error code
   */
  
  static void *gfs2_follow_link(struct dentry *dentry, struct nameidata *nd)
  {
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
799
  	struct gfs2_inode *ip = GFS2_I(dentry->d_inode);
b3b94faa5   David Teigland   [GFS2] The core o...
800
801
802
  	char array[GFS2_FAST_NAME_SIZE], *buf = array;
  	unsigned int len = GFS2_FAST_NAME_SIZE;
  	int error;
b3b94faa5   David Teigland   [GFS2] The core o...
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
  	error = gfs2_readlinki(ip, &buf, &len);
  	if (!error) {
  		error = vfs_follow_link(nd, buf);
  		if (buf != array)
  			kfree(buf);
  	}
  
  	return ERR_PTR(error);
  }
  
  /**
   * gfs2_permission -
   * @inode:
   * @mask:
   * @nd: passed from Linux VFS, ignored by us
   *
300c7d75f   Steven Whitehouse   [GFS2] Fix recurs...
819
820
821
822
   * 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...
823
824
825
826
827
   * Returns: errno
   */
  
  static int gfs2_permission(struct inode *inode, int mask, struct nameidata *nd)
  {
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
828
  	struct gfs2_inode *ip = GFS2_I(inode);
b3b94faa5   David Teigland   [GFS2] The core o...
829
830
  	struct gfs2_holder i_gh;
  	int error;
300c7d75f   Steven Whitehouse   [GFS2] Fix recurs...
831
  	int unlock = 0;
b3b94faa5   David Teigland   [GFS2] The core o...
832

300c7d75f   Steven Whitehouse   [GFS2] Fix recurs...
833
834
835
836
837
838
  	if (gfs2_glock_is_locked_by_me(ip->i_gl) == 0) {
  		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...
839

77386e1f6   Steven Whitehouse   [GFS2] Remove gfs...
840
  	error = generic_permission(inode, mask, gfs2_check_acl);
300c7d75f   Steven Whitehouse   [GFS2] Fix recurs...
841
  	if (unlock)
b3b94faa5   David Teigland   [GFS2] The core o...
842
  		gfs2_glock_dq_uninit(&i_gh);
b3b94faa5   David Teigland   [GFS2] The core o...
843
844
845
846
847
848
  
  	return error;
  }
  
  static int setattr_size(struct inode *inode, struct iattr *attr)
  {
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
849
  	struct gfs2_inode *ip = GFS2_I(inode);
b3b94faa5   David Teigland   [GFS2] The core o...
850
851
852
853
854
855
856
  	int error;
  
  	if (attr->ia_size != ip->i_di.di_size) {
  		error = vmtruncate(inode, attr->ia_size);
  		if (error)
  			return error;
  	}
aa6a85a97   Steven Whitehouse   [GFS2] Remove poi...
857
  	error = gfs2_truncatei(ip, attr->ia_size);
090ffaa55   Wendy Cheng   [GFS2] inode size...
858
859
  	if (error && (inode->i_size != ip->i_di.di_size))
  		i_size_write(inode, ip->i_di.di_size);
b3b94faa5   David Teigland   [GFS2] The core o...
860
861
862
863
864
865
  
  	return error;
  }
  
  static int setattr_chown(struct inode *inode, struct iattr *attr)
  {
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
866
867
  	struct gfs2_inode *ip = GFS2_I(inode);
  	struct gfs2_sbd *sdp = GFS2_SB(inode);
b3b94faa5   David Teigland   [GFS2] The core o...
868
  	struct buffer_head *dibh;
cd915493f   Steven Whitehouse   [GFS2] Change all...
869
  	u32 ouid, ogid, nuid, ngid;
b3b94faa5   David Teigland   [GFS2] The core o...
870
  	int error;
2933f9254   Steven Whitehouse   [GFS2] Shrink gfs...
871
872
  	ouid = inode->i_uid;
  	ogid = inode->i_gid;
b3b94faa5   David Teigland   [GFS2] The core o...
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
  	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;
  
  	gfs2_alloc_get(ip);
  
  	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;
  
  	error = gfs2_meta_inode_buffer(ip, &dibh);
  	if (error)
  		goto out_end_trans;
  
  	error = inode_setattr(inode, attr);
  	gfs2_assert_warn(sdp, !error);
b3b94faa5   David Teigland   [GFS2] The core o...
903

d4e9c4c3b   Steven Whitehouse   [GFS2] Add an add...
904
  	gfs2_trans_add_bh(ip->i_gl, dibh, 1);
539e5d6b7   Steven Whitehouse   [GFS2] Change arg...
905
  	gfs2_dinode_out(ip, dibh->b_data);
b3b94faa5   David Teigland   [GFS2] The core o...
906
907
908
  	brelse(dibh);
  
  	if (ouid != NO_QUOTA_CHANGE || ogid != NO_QUOTA_CHANGE) {
af18ddb88   Steven Whitehouse   [GFS2] Eliminate ...
909
910
  		gfs2_quota_change(ip, -ip->i_di.di_blocks, ouid, ogid);
  		gfs2_quota_change(ip, ip->i_di.di_blocks, nuid, ngid);
b3b94faa5   David Teigland   [GFS2] The core o...
911
  	}
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
912
  out_end_trans:
b3b94faa5   David Teigland   [GFS2] The core o...
913
  	gfs2_trans_end(sdp);
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
914
  out_gunlock_q:
b3b94faa5   David Teigland   [GFS2] The core o...
915
  	gfs2_quota_unlock(ip);
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
916
  out_alloc:
b3b94faa5   David Teigland   [GFS2] The core o...
917
  	gfs2_alloc_put(ip);
b3b94faa5   David Teigland   [GFS2] The core o...
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
  	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...
935
  	struct gfs2_inode *ip = GFS2_I(inode);
b3b94faa5   David Teigland   [GFS2] The core o...
936
937
  	struct gfs2_holder i_gh;
  	int error;
b3b94faa5   David Teigland   [GFS2] The core o...
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
  	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)
  		error = setattr_size(inode, attr);
  	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
  		error = gfs2_setattr_simple(ip, attr);
a91ea69ff   Steven Whitehouse   [GFS2] Align all ...
958
  out:
b3b94faa5   David Teigland   [GFS2] The core o...
959
  	gfs2_glock_dq_uninit(&i_gh);
b3b94faa5   David Teigland   [GFS2] The core o...
960
961
  	if (!error)
  		mark_inode_dirty(inode);
b3b94faa5   David Teigland   [GFS2] The core o...
962
963
964
965
966
  	return error;
  }
  
  /**
   * gfs2_getattr - Read out an inode's attributes
26c1a5741   Steven Whitehouse   [GFS2] More code ...
967
   * @mnt: The vfsmount the inode is being accessed from
b3b94faa5   David Teigland   [GFS2] The core o...
968
969
970
   * @dentry: The dentry to stat
   * @stat: The inode's stats
   *
dcf3dd852   Steven Whitehouse   [GFS2] Fix recurs...
971
972
973
974
975
976
   * 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...
977
978
979
980
981
982
983
   * 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...
984
  	struct gfs2_inode *ip = GFS2_I(inode);
b3b94faa5   David Teigland   [GFS2] The core o...
985
986
  	struct gfs2_holder gh;
  	int error;
dcf3dd852   Steven Whitehouse   [GFS2] Fix recurs...
987
  	int unlock = 0;
b3b94faa5   David Teigland   [GFS2] The core o...
988

dcf3dd852   Steven Whitehouse   [GFS2] Fix recurs...
989
990
991
992
993
  	if (gfs2_glock_is_locked_by_me(ip->i_gl) == 0) {
  		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...
994
  	}
dcf3dd852   Steven Whitehouse   [GFS2] Fix recurs...
995
  	generic_fillattr(inode, stat);
d7c103d0b   Steven Whitehouse   [GFS2] Fix recurs...
996
  	if (unlock)
dcf3dd852   Steven Whitehouse   [GFS2] Fix recurs...
997
998
999
  		gfs2_glock_dq_uninit(&gh);
  
  	return 0;
b3b94faa5   David Teigland   [GFS2] The core o...
1000
1001
1002
1003
1004
  }
  
  static int gfs2_setxattr(struct dentry *dentry, const char *name,
  			 const void *data, size_t size, int flags)
  {
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
1005
  	struct inode *inode = dentry->d_inode;
b3b94faa5   David Teigland   [GFS2] The core o...
1006
  	struct gfs2_ea_request er;
b3b94faa5   David Teigland   [GFS2] The core o...
1007
1008
1009
1010
1011
1012
1013
1014
  	memset(&er, 0, sizeof(struct gfs2_ea_request));
  	er.er_type = gfs2_ea_name2type(name, &er.er_name);
  	if (er.er_type == GFS2_EATYPE_UNUSED)
  		return -EOPNOTSUPP;
  	er.er_data = (char *)data;
  	er.er_name_len = strlen(er.er_name);
  	er.er_data_len = size;
  	er.er_flags = flags;
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
1015
  	gfs2_assert_warn(GFS2_SB(inode), !(er.er_flags & GFS2_ERF_MODE));
b3b94faa5   David Teigland   [GFS2] The core o...
1016

feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
1017
  	return gfs2_ea_set(GFS2_I(inode), &er);
b3b94faa5   David Teigland   [GFS2] The core o...
1018
1019
1020
1021
1022
1023
  }
  
  static ssize_t gfs2_getxattr(struct dentry *dentry, const char *name,
  			     void *data, size_t size)
  {
  	struct gfs2_ea_request er;
b3b94faa5   David Teigland   [GFS2] The core o...
1024
1025
1026
1027
1028
1029
1030
  	memset(&er, 0, sizeof(struct gfs2_ea_request));
  	er.er_type = gfs2_ea_name2type(name, &er.er_name);
  	if (er.er_type == GFS2_EATYPE_UNUSED)
  		return -EOPNOTSUPP;
  	er.er_data = data;
  	er.er_name_len = strlen(er.er_name);
  	er.er_data_len = size;
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
1031
  	return gfs2_ea_get(GFS2_I(dentry->d_inode), &er);
b3b94faa5   David Teigland   [GFS2] The core o...
1032
1033
1034
1035
1036
  }
  
  static ssize_t gfs2_listxattr(struct dentry *dentry, char *buffer, size_t size)
  {
  	struct gfs2_ea_request er;
b3b94faa5   David Teigland   [GFS2] The core o...
1037
1038
1039
  	memset(&er, 0, sizeof(struct gfs2_ea_request));
  	er.er_data = (size) ? buffer : NULL;
  	er.er_data_len = size;
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
1040
  	return gfs2_ea_list(GFS2_I(dentry->d_inode), &er);
b3b94faa5   David Teigland   [GFS2] The core o...
1041
1042
1043
1044
1045
  }
  
  static int gfs2_removexattr(struct dentry *dentry, const char *name)
  {
  	struct gfs2_ea_request er;
b3b94faa5   David Teigland   [GFS2] The core o...
1046
1047
1048
1049
1050
  	memset(&er, 0, sizeof(struct gfs2_ea_request));
  	er.er_type = gfs2_ea_name2type(name, &er.er_name);
  	if (er.er_type == GFS2_EATYPE_UNUSED)
  		return -EOPNOTSUPP;
  	er.er_name_len = strlen(er.er_name);
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
1051
  	return gfs2_ea_remove(GFS2_I(dentry->d_inode), &er);
b3b94faa5   David Teigland   [GFS2] The core o...
1052
  }
92e1d5be9   Arjan van de Ven   [PATCH] mark stru...
1053
  const struct inode_operations gfs2_file_iops = {
b3b94faa5   David Teigland   [GFS2] The core o...
1054
1055
1056
1057
1058
1059
1060
1061
  	.permission = gfs2_permission,
  	.setattr = gfs2_setattr,
  	.getattr = gfs2_getattr,
  	.setxattr = gfs2_setxattr,
  	.getxattr = gfs2_getxattr,
  	.listxattr = gfs2_listxattr,
  	.removexattr = gfs2_removexattr,
  };
92e1d5be9   Arjan van de Ven   [PATCH] mark stru...
1062
  const struct inode_operations gfs2_dev_iops = {
b3b94faa5   David Teigland   [GFS2] The core o...
1063
1064
1065
1066
1067
1068
1069
1070
  	.permission = gfs2_permission,
  	.setattr = gfs2_setattr,
  	.getattr = gfs2_getattr,
  	.setxattr = gfs2_setxattr,
  	.getxattr = gfs2_getxattr,
  	.listxattr = gfs2_listxattr,
  	.removexattr = gfs2_removexattr,
  };
92e1d5be9   Arjan van de Ven   [PATCH] mark stru...
1071
  const struct inode_operations gfs2_dir_iops = {
b3b94faa5   David Teigland   [GFS2] The core o...
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
  	.create = gfs2_create,
  	.lookup = gfs2_lookup,
  	.link = gfs2_link,
  	.unlink = gfs2_unlink,
  	.symlink = gfs2_symlink,
  	.mkdir = gfs2_mkdir,
  	.rmdir = gfs2_rmdir,
  	.mknod = gfs2_mknod,
  	.rename = gfs2_rename,
  	.permission = gfs2_permission,
  	.setattr = gfs2_setattr,
  	.getattr = gfs2_getattr,
  	.setxattr = gfs2_setxattr,
  	.getxattr = gfs2_getxattr,
  	.listxattr = gfs2_listxattr,
  	.removexattr = gfs2_removexattr,
  };
92e1d5be9   Arjan van de Ven   [PATCH] mark stru...
1089
  const struct inode_operations gfs2_symlink_iops = {
b3b94faa5   David Teigland   [GFS2] The core o...
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
  	.readlink = gfs2_readlink,
  	.follow_link = gfs2_follow_link,
  	.permission = gfs2_permission,
  	.setattr = gfs2_setattr,
  	.getattr = gfs2_getattr,
  	.setxattr = gfs2_setxattr,
  	.getxattr = gfs2_getxattr,
  	.listxattr = gfs2_listxattr,
  	.removexattr = gfs2_removexattr,
  };