Blame view

fs/jfs/namei.c 36.5 KB
1a59d1b8e   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-or-later
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
3
4
  /*
   *   Copyright (C) International Business Machines Corp., 2000-2004
   *   Portions Copyright (C) Christoph Hellwig, 2001-2002
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5
6
7
   */
  
  #include <linux/fs.h>
2bc334dcc   Nick Piggin   jfs: dont overwri...
8
  #include <linux/namei.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
9
10
  #include <linux/ctype.h>
  #include <linux/quotaops.h>
d425de704   Christoph Hellwig   jfs: new export ops
11
  #include <linux/exportfs.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
12
13
14
15
16
17
18
19
20
21
  #include "jfs_incore.h"
  #include "jfs_superblock.h"
  #include "jfs_inode.h"
  #include "jfs_dinode.h"
  #include "jfs_dmap.h"
  #include "jfs_unicode.h"
  #include "jfs_metapage.h"
  #include "jfs_xattr.h"
  #include "jfs_acl.h"
  #include "jfs_debug.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
22
23
24
  /*
   * forward references
   */
ad28b4ef1   Al Viro   constify dentry_o...
25
  const struct dentry_operations jfs_ci_dentry_operations;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
26
27
28
29
  
  static s64 commitZeroLink(tid_t, struct inode *);
  
  /*
4f4b401bf   Dave Kleikamp   JFS: allow extend...
30
31
   * NAME:	free_ea_wmap(inode)
   *
63f83c9fc   Dave Kleikamp   JFS: White space ...
32
   * FUNCTION:	free uncommitted extended attributes from working map
4f4b401bf   Dave Kleikamp   JFS: allow extend...
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
   *
   */
  static inline void free_ea_wmap(struct inode *inode)
  {
  	dxd_t *ea = &JFS_IP(inode)->ea;
  
  	if (ea->flag & DXD_EXTENT) {
  		/* free EA pages from cache */
  		invalidate_dxd_metapages(inode, *ea);
  		dbFree(inode, addressDXD(ea), lengthDXD(ea));
  	}
  	ea->flag = 0;
  }
  
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
48
49
50
51
52
   * NAME:	jfs_create(dip, dentry, mode)
   *
   * FUNCTION:	create a regular file in the parent directory <dip>
   *		with name = <from dentry> and mode = <mode>
   *
63f83c9fc   Dave Kleikamp   JFS: White space ...
53
   * PARAMETER:	dip	- parent directory vnode
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
54
55
56
57
58
59
60
   *		dentry	- dentry of new file
   *		mode	- create mode (rwxrwxrwx).
   *		nd- nd struct
   *
   * RETURN:	Errors from subroutines
   *
   */
4acdaf27e   Al Viro   switch ->create()...
61
  static int jfs_create(struct inode *dip, struct dentry *dentry, umode_t mode,
ebfc3b49a   Al Viro   don't pass nameid...
62
  		bool excl)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
63
64
65
66
67
68
69
70
71
  {
  	int rc = 0;
  	tid_t tid;		/* transaction id */
  	struct inode *ip = NULL;	/* child directory inode */
  	ino_t ino;
  	struct component_name dname;	/* child directory name */
  	struct btstack btstack;
  	struct inode *iplist[2];
  	struct tblock *tblk;
a455589f1   Al Viro   assorted conversi...
72
  	jfs_info("jfs_create: dip:0x%p name:%pd", dip, dentry);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
73

acc84b05b   Dave Kleikamp   jfs: Handle error...
74
75
76
  	rc = dquot_initialize(dip);
  	if (rc)
  		goto out1;
907f4554e   Christoph Hellwig   dquot: move dquot...
77

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
78
79
80
81
82
83
84
85
86
87
88
89
90
  	/*
  	 * search parent directory for entry/freespace
  	 * (dtSearch() returns parent directory page pinned)
  	 */
  	if ((rc = get_UCSname(&dname, dentry)))
  		goto out1;
  
  	/*
  	 * Either iAlloc() or txBegin() may block.  Deadlock can occur if we
  	 * block there while holding dtree page, so we allocate the inode &
  	 * begin the transaction before we search the directory.
  	 */
  	ip = ialloc(dip, mode);
087387f90   Akinobu Mita   [PATCH] JFS: retu...
91
92
  	if (IS_ERR(ip)) {
  		rc = PTR_ERR(ip);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
93
94
95
96
  		goto out2;
  	}
  
  	tid = txBegin(dip->i_sb, 0);
82d5b9a7c   Dave Kleikamp   JFS: Add lockdep ...
97
98
  	mutex_lock_nested(&JFS_IP(dip)->commit_mutex, COMMIT_MUTEX_PARENT);
  	mutex_lock_nested(&JFS_IP(ip)->commit_mutex, COMMIT_MUTEX_CHILD);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
99

4f4b401bf   Dave Kleikamp   JFS: allow extend...
100
101
102
  	rc = jfs_init_acl(tid, ip, dip);
  	if (rc)
  		goto out3;
2a7dba391   Eric Paris   fs/vfs/security: ...
103
  	rc = jfs_init_security(tid, ip, dip, &dentry->d_name);
1d15b10f9   Dave Kleikamp   JFS: Implement jf...
104
105
106
107
  	if (rc) {
  		txAbort(tid, 0);
  		goto out3;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
108
109
  	if ((rc = dtSearch(dip, &dname, &ino, &btstack, JFS_CREATE))) {
  		jfs_err("jfs_create: dtSearch returned %d", rc);
4f4b401bf   Dave Kleikamp   JFS: allow extend...
110
  		txAbort(tid, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
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
  		goto out3;
  	}
  
  	tblk = tid_to_tblock(tid);
  	tblk->xflag |= COMMIT_CREATE;
  	tblk->ino = ip->i_ino;
  	tblk->u.ixpxd = JFS_IP(ip)->ixpxd;
  
  	iplist[0] = dip;
  	iplist[1] = ip;
  
  	/*
  	 * initialize the child XAD tree root in-line in inode
  	 */
  	xtInitRoot(tid, ip);
  
  	/*
  	 * create entry in parent directory for child directory
  	 * (dtInsert() releases parent directory page)
  	 */
  	ino = ip->i_ino;
  	if ((rc = dtInsert(tid, dip, &dname, &ino, &btstack))) {
  		if (rc == -EIO) {
  			jfs_err("jfs_create: dtInsert returned -EIO");
  			txAbort(tid, 1);	/* Marks Filesystem dirty */
  		} else
  			txAbort(tid, 0);	/* Filesystem full */
  		goto out3;
  	}
  
  	ip->i_op = &jfs_file_inode_operations;
  	ip->i_fop = &jfs_file_operations;
  	ip->i_mapping->a_ops = &jfs_aops;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
144
  	mark_inode_dirty(ip);
078cd8279   Deepa Dinamani   fs: Replace CURRE...
145
  	dip->i_ctime = dip->i_mtime = current_time(dip);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
146
147
148
149
150
151
152
  
  	mark_inode_dirty(dip);
  
  	rc = txCommit(tid, 2, &iplist[0], 0);
  
        out3:
  	txEnd(tid);
1de87444f   Ingo Molnar   JFS: semaphore to...
153
  	mutex_unlock(&JFS_IP(ip)->commit_mutex);
48ce8b056   Evgeniy Dushistov   JFS: commit_mutex...
154
  	mutex_unlock(&JFS_IP(dip)->commit_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
155
  	if (rc) {
4f4b401bf   Dave Kleikamp   JFS: allow extend...
156
  		free_ea_wmap(ip);
6d6b77f16   Miklos Szeredi   filesystems: add ...
157
  		clear_nlink(ip);
a6cbedfa8   Al Viro   jfs: switch to di...
158
  		discard_new_inode(ip);
1f3403fa6   Dave Kleikamp   nfsd race fixes: jfs
159
  	} else {
1e2e547a9   Al Viro   do d_instantiate/...
160
  		d_instantiate_new(dentry, ip);
1f3403fa6   Dave Kleikamp   nfsd race fixes: jfs
161
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
162
163
164
  
        out2:
  	free_UCSname(&dname);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
165
166
167
168
169
170
171
172
173
174
175
176
177
        out1:
  
  	jfs_info("jfs_create: rc:%d", rc);
  	return rc;
  }
  
  
  /*
   * NAME:	jfs_mkdir(dip, dentry, mode)
   *
   * FUNCTION:	create a child directory in the parent directory <dip>
   *		with name = <from dentry> and mode = <mode>
   *
63f83c9fc   Dave Kleikamp   JFS: White space ...
178
   * PARAMETER:	dip	- parent directory vnode
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
179
180
181
182
183
184
   *		dentry	- dentry of child directory
   *		mode	- create mode (rwxrwxrwx).
   *
   * RETURN:	Errors from subroutines
   *
   * note:
a83722f45   Colin Ian King   jfs: fix spelling...
185
   * EACCES: user needs search+write permission on the parent directory
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
186
   */
18bb1db3e   Al Viro   switch vfs_mkdir(...
187
  static int jfs_mkdir(struct inode *dip, struct dentry *dentry, umode_t mode)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
188
189
190
191
192
193
194
195
196
  {
  	int rc = 0;
  	tid_t tid;		/* transaction id */
  	struct inode *ip = NULL;	/* child directory inode */
  	ino_t ino;
  	struct component_name dname;	/* child directory name */
  	struct btstack btstack;
  	struct inode *iplist[2];
  	struct tblock *tblk;
a455589f1   Al Viro   assorted conversi...
197
  	jfs_info("jfs_mkdir: dip:0x%p name:%pd", dip, dentry);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
198

acc84b05b   Dave Kleikamp   jfs: Handle error...
199
200
201
  	rc = dquot_initialize(dip);
  	if (rc)
  		goto out1;
907f4554e   Christoph Hellwig   dquot: move dquot...
202

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
203
204
205
206
207
208
209
210
211
212
213
214
215
  	/*
  	 * search parent directory for entry/freespace
  	 * (dtSearch() returns parent directory page pinned)
  	 */
  	if ((rc = get_UCSname(&dname, dentry)))
  		goto out1;
  
  	/*
  	 * Either iAlloc() or txBegin() may block.  Deadlock can occur if we
  	 * block there while holding dtree page, so we allocate the inode &
  	 * begin the transaction before we search the directory.
  	 */
  	ip = ialloc(dip, S_IFDIR | mode);
087387f90   Akinobu Mita   [PATCH] JFS: retu...
216
217
  	if (IS_ERR(ip)) {
  		rc = PTR_ERR(ip);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
218
219
220
221
  		goto out2;
  	}
  
  	tid = txBegin(dip->i_sb, 0);
82d5b9a7c   Dave Kleikamp   JFS: Add lockdep ...
222
223
  	mutex_lock_nested(&JFS_IP(dip)->commit_mutex, COMMIT_MUTEX_PARENT);
  	mutex_lock_nested(&JFS_IP(ip)->commit_mutex, COMMIT_MUTEX_CHILD);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
224

4f4b401bf   Dave Kleikamp   JFS: allow extend...
225
226
227
  	rc = jfs_init_acl(tid, ip, dip);
  	if (rc)
  		goto out3;
2a7dba391   Eric Paris   fs/vfs/security: ...
228
  	rc = jfs_init_security(tid, ip, dip, &dentry->d_name);
1d15b10f9   Dave Kleikamp   JFS: Implement jf...
229
230
231
232
  	if (rc) {
  		txAbort(tid, 0);
  		goto out3;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
233
234
  	if ((rc = dtSearch(dip, &dname, &ino, &btstack, JFS_CREATE))) {
  		jfs_err("jfs_mkdir: dtSearch returned %d", rc);
4f4b401bf   Dave Kleikamp   JFS: allow extend...
235
  		txAbort(tid, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
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
  		goto out3;
  	}
  
  	tblk = tid_to_tblock(tid);
  	tblk->xflag |= COMMIT_CREATE;
  	tblk->ino = ip->i_ino;
  	tblk->u.ixpxd = JFS_IP(ip)->ixpxd;
  
  	iplist[0] = dip;
  	iplist[1] = ip;
  
  	/*
  	 * initialize the child directory in-line in inode
  	 */
  	dtInitRoot(tid, ip, dip->i_ino);
  
  	/*
  	 * create entry in parent directory for child directory
  	 * (dtInsert() releases parent directory page)
  	 */
  	ino = ip->i_ino;
  	if ((rc = dtInsert(tid, dip, &dname, &ino, &btstack))) {
  		if (rc == -EIO) {
  			jfs_err("jfs_mkdir: dtInsert returned -EIO");
  			txAbort(tid, 1);	/* Marks Filesystem dirty */
  		} else
  			txAbort(tid, 0);	/* Filesystem full */
  		goto out3;
  	}
bfe868486   Miklos Szeredi   filesystems: add ...
265
  	set_nlink(ip, 2);	/* for '.' */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
266
267
  	ip->i_op = &jfs_dir_inode_operations;
  	ip->i_fop = &jfs_dir_operations;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
268
269
270
  	mark_inode_dirty(ip);
  
  	/* update parent directory inode */
d8c76e6f4   Dave Hansen   [PATCH] r/o bind ...
271
  	inc_nlink(dip);		/* for '..' from child directory */
078cd8279   Deepa Dinamani   fs: Replace CURRE...
272
  	dip->i_ctime = dip->i_mtime = current_time(dip);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
273
274
275
276
277
278
  	mark_inode_dirty(dip);
  
  	rc = txCommit(tid, 2, &iplist[0], 0);
  
        out3:
  	txEnd(tid);
1de87444f   Ingo Molnar   JFS: semaphore to...
279
  	mutex_unlock(&JFS_IP(ip)->commit_mutex);
48ce8b056   Evgeniy Dushistov   JFS: commit_mutex...
280
  	mutex_unlock(&JFS_IP(dip)->commit_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
281
  	if (rc) {
4f4b401bf   Dave Kleikamp   JFS: allow extend...
282
  		free_ea_wmap(ip);
6d6b77f16   Miklos Szeredi   filesystems: add ...
283
  		clear_nlink(ip);
a6cbedfa8   Al Viro   jfs: switch to di...
284
  		discard_new_inode(ip);
1f3403fa6   Dave Kleikamp   nfsd race fixes: jfs
285
  	} else {
1e2e547a9   Al Viro   do d_instantiate/...
286
  		d_instantiate_new(dentry, ip);
1f3403fa6   Dave Kleikamp   nfsd race fixes: jfs
287
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
288
289
290
  
        out2:
  	free_UCSname(&dname);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
291
292
293
294
295
296
297
298
299
300
301
302
  
        out1:
  
  	jfs_info("jfs_mkdir: rc:%d", rc);
  	return rc;
  }
  
  /*
   * NAME:	jfs_rmdir(dip, dentry)
   *
   * FUNCTION:	remove a link to child directory
   *
63f83c9fc   Dave Kleikamp   JFS: White space ...
303
   * PARAMETER:	dip	- parent inode
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
304
305
306
   *		dentry	- child directory dentry
   *
   * RETURN:	-EINVAL	- if name is . or ..
f720e3ba5   Dave Kleikamp   JFS: Whitespace c...
307
   *		-EINVAL - if . or .. exist but are invalid.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
308
309
310
   *		errors from subroutines
   *
   * note:
63f83c9fc   Dave Kleikamp   JFS: White space ...
311
312
313
314
   * if other threads have the directory open when the last link
   * is removed, the "." and ".." entries, if present, are removed before
   * rmdir() returns and no new entries may be created in the directory,
   * but the directory is not removed until the last reference to
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
315
316
317
318
319
320
   * the directory is released (cf.unlink() of regular file).
   */
  static int jfs_rmdir(struct inode *dip, struct dentry *dentry)
  {
  	int rc;
  	tid_t tid;		/* transaction id */
2b0143b5c   David Howells   VFS: normal files...
321
  	struct inode *ip = d_inode(dentry);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
322
323
324
325
  	ino_t ino;
  	struct component_name dname;
  	struct inode *iplist[2];
  	struct tblock *tblk;
a455589f1   Al Viro   assorted conversi...
326
  	jfs_info("jfs_rmdir: dip:0x%p name:%pd", dip, dentry);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
327
328
  
  	/* Init inode for quota operations. */
acc84b05b   Dave Kleikamp   jfs: Handle error...
329
330
331
332
333
334
  	rc = dquot_initialize(dip);
  	if (rc)
  		goto out;
  	rc = dquot_initialize(ip);
  	if (rc)
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
335
336
337
338
339
340
341
342
343
344
345
346
  
  	/* directory must be empty to be removed */
  	if (!dtEmpty(ip)) {
  		rc = -ENOTEMPTY;
  		goto out;
  	}
  
  	if ((rc = get_UCSname(&dname, dentry))) {
  		goto out;
  	}
  
  	tid = txBegin(dip->i_sb, 0);
82d5b9a7c   Dave Kleikamp   JFS: Add lockdep ...
347
348
  	mutex_lock_nested(&JFS_IP(dip)->commit_mutex, COMMIT_MUTEX_PARENT);
  	mutex_lock_nested(&JFS_IP(ip)->commit_mutex, COMMIT_MUTEX_CHILD);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
  
  	iplist[0] = dip;
  	iplist[1] = ip;
  
  	tblk = tid_to_tblock(tid);
  	tblk->xflag |= COMMIT_DELETE;
  	tblk->u.ip = ip;
  
  	/*
  	 * delete the entry of target directory from parent directory
  	 */
  	ino = ip->i_ino;
  	if ((rc = dtDelete(tid, dip, &dname, &ino, JFS_REMOVE))) {
  		jfs_err("jfs_rmdir: dtDelete returned %d", rc);
  		if (rc == -EIO)
  			txAbort(tid, 1);
  		txEnd(tid);
1de87444f   Ingo Molnar   JFS: semaphore to...
366
  		mutex_unlock(&JFS_IP(ip)->commit_mutex);
48ce8b056   Evgeniy Dushistov   JFS: commit_mutex...
367
  		mutex_unlock(&JFS_IP(dip)->commit_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
368
369
370
371
372
373
374
  
  		goto out2;
  	}
  
  	/* update parent directory's link count corresponding
  	 * to ".." entry of the target directory deleted
  	 */
078cd8279   Deepa Dinamani   fs: Replace CURRE...
375
  	dip->i_ctime = dip->i_mtime = current_time(dip);
9a53c3a78   Dave Hansen   [PATCH] r/o bind ...
376
  	inode_dec_link_count(dip);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
  
  	/*
  	 * OS/2 could have created EA and/or ACL
  	 */
  	/* free EA from both persistent and working map */
  	if (JFS_IP(ip)->ea.flag & DXD_EXTENT) {
  		/* free EA pages */
  		txEA(tid, ip, &JFS_IP(ip)->ea, NULL);
  	}
  	JFS_IP(ip)->ea.flag = 0;
  
  	/* free ACL from both persistent and working map */
  	if (JFS_IP(ip)->acl.flag & DXD_EXTENT) {
  		/* free ACL pages */
  		txEA(tid, ip, &JFS_IP(ip)->acl, NULL);
  	}
  	JFS_IP(ip)->acl.flag = 0;
  
  	/* mark the target directory as deleted */
ce71ec368   Dave Hansen   [PATCH] r/o bind ...
396
  	clear_nlink(ip);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
397
398
399
400
401
  	mark_inode_dirty(ip);
  
  	rc = txCommit(tid, 2, &iplist[0], 0);
  
  	txEnd(tid);
1de87444f   Ingo Molnar   JFS: semaphore to...
402
  	mutex_unlock(&JFS_IP(ip)->commit_mutex);
48ce8b056   Evgeniy Dushistov   JFS: commit_mutex...
403
  	mutex_unlock(&JFS_IP(dip)->commit_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
  
  	/*
  	 * Truncating the directory index table is not guaranteed.  It
  	 * may need to be done iteratively
  	 */
  	if (test_cflag(COMMIT_Stale, dip)) {
  		if (dip->i_size > 1)
  			jfs_truncate_nolock(dip, 0);
  
  		clear_cflag(COMMIT_Stale, dip);
  	}
  
        out2:
  	free_UCSname(&dname);
  
        out:
  	jfs_info("jfs_rmdir: rc:%d", rc);
  	return rc;
  }
  
  /*
   * NAME:	jfs_unlink(dip, dentry)
   *
63f83c9fc   Dave Kleikamp   JFS: White space ...
427
   * FUNCTION:	remove a link to object <vp> named by <name>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
428
429
   *		from parent directory <dvp>
   *
63f83c9fc   Dave Kleikamp   JFS: White space ...
430
431
   * PARAMETER:	dip	- inode of parent directory
   *		dentry	- dentry of object to be removed
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
   *
   * RETURN:	errors from subroutines
   *
   * note:
   * temporary file: if one or more processes have the file open
   * when the last link is removed, the link will be removed before
   * unlink() returns, but the removal of the file contents will be
   * postponed until all references to the files are closed.
   *
   * JFS does NOT support unlink() on directories.
   *
   */
  static int jfs_unlink(struct inode *dip, struct dentry *dentry)
  {
  	int rc;
  	tid_t tid;		/* transaction id */
2b0143b5c   David Howells   VFS: normal files...
448
  	struct inode *ip = d_inode(dentry);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
449
450
451
452
453
454
  	ino_t ino;
  	struct component_name dname;	/* object name */
  	struct inode *iplist[2];
  	struct tblock *tblk;
  	s64 new_size = 0;
  	int commit_flag;
a455589f1   Al Viro   assorted conversi...
455
  	jfs_info("jfs_unlink: dip:0x%p name:%pd", dip, dentry);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
456
457
  
  	/* Init inode for quota operations. */
acc84b05b   Dave Kleikamp   jfs: Handle error...
458
459
460
461
462
463
  	rc = dquot_initialize(dip);
  	if (rc)
  		goto out;
  	rc = dquot_initialize(ip);
  	if (rc)
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
464
465
466
  
  	if ((rc = get_UCSname(&dname, dentry)))
  		goto out;
82d5b9a7c   Dave Kleikamp   JFS: Add lockdep ...
467
  	IWRITE_LOCK(ip, RDWRLOCK_NORMAL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
468
469
  
  	tid = txBegin(dip->i_sb, 0);
82d5b9a7c   Dave Kleikamp   JFS: Add lockdep ...
470
471
  	mutex_lock_nested(&JFS_IP(dip)->commit_mutex, COMMIT_MUTEX_PARENT);
  	mutex_lock_nested(&JFS_IP(ip)->commit_mutex, COMMIT_MUTEX_CHILD);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
472
473
474
475
476
477
478
479
480
481
482
483
484
  
  	iplist[0] = dip;
  	iplist[1] = ip;
  
  	/*
  	 * delete the entry of target file from parent directory
  	 */
  	ino = ip->i_ino;
  	if ((rc = dtDelete(tid, dip, &dname, &ino, JFS_REMOVE))) {
  		jfs_err("jfs_unlink: dtDelete returned %d", rc);
  		if (rc == -EIO)
  			txAbort(tid, 1);	/* Marks FS Dirty */
  		txEnd(tid);
1de87444f   Ingo Molnar   JFS: semaphore to...
485
  		mutex_unlock(&JFS_IP(ip)->commit_mutex);
48ce8b056   Evgeniy Dushistov   JFS: commit_mutex...
486
  		mutex_unlock(&JFS_IP(dip)->commit_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
487
488
489
490
491
  		IWRITE_UNLOCK(ip);
  		goto out1;
  	}
  
  	ASSERT(ip->i_nlink);
078cd8279   Deepa Dinamani   fs: Replace CURRE...
492
  	ip->i_ctime = dip->i_ctime = dip->i_mtime = current_time(ip);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
493
494
495
  	mark_inode_dirty(dip);
  
  	/* update target's inode */
9a53c3a78   Dave Hansen   [PATCH] r/o bind ...
496
  	inode_dec_link_count(ip);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
497
498
  
  	/*
f720e3ba5   Dave Kleikamp   JFS: Whitespace c...
499
  	 *	commit zero link count object
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
500
501
502
503
504
505
506
  	 */
  	if (ip->i_nlink == 0) {
  		assert(!test_cflag(COMMIT_Nolink, ip));
  		/* free block resources */
  		if ((new_size = commitZeroLink(tid, ip)) < 0) {
  			txAbort(tid, 1);	/* Marks FS Dirty */
  			txEnd(tid);
1de87444f   Ingo Molnar   JFS: semaphore to...
507
  			mutex_unlock(&JFS_IP(ip)->commit_mutex);
48ce8b056   Evgeniy Dushistov   JFS: commit_mutex...
508
  			mutex_unlock(&JFS_IP(dip)->commit_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
  			IWRITE_UNLOCK(ip);
  			rc = new_size;
  			goto out1;
  		}
  		tblk = tid_to_tblock(tid);
  		tblk->xflag |= COMMIT_DELETE;
  		tblk->u.ip = ip;
  	}
  
  	/*
  	 * Incomplete truncate of file data can
  	 * result in timing problems unless we synchronously commit the
  	 * transaction.
  	 */
  	if (new_size)
  		commit_flag = COMMIT_SYNC;
  	else
  		commit_flag = 0;
  
  	/*
  	 * If xtTruncate was incomplete, commit synchronously to avoid
  	 * timing complications
  	 */
  	rc = txCommit(tid, 2, &iplist[0], commit_flag);
  
  	txEnd(tid);
1de87444f   Ingo Molnar   JFS: semaphore to...
535
  	mutex_unlock(&JFS_IP(ip)->commit_mutex);
48ce8b056   Evgeniy Dushistov   JFS: commit_mutex...
536
  	mutex_unlock(&JFS_IP(dip)->commit_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
537
538
539
  
  	while (new_size && (rc == 0)) {
  		tid = txBegin(dip->i_sb, 0);
1de87444f   Ingo Molnar   JFS: semaphore to...
540
  		mutex_lock(&JFS_IP(ip)->commit_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
541
542
543
544
545
546
547
  		new_size = xtTruncate_pmap(tid, ip, new_size);
  		if (new_size < 0) {
  			txAbort(tid, 1);	/* Marks FS Dirty */
  			rc = new_size;
  		} else
  			rc = txCommit(tid, 2, &iplist[0], COMMIT_SYNC);
  		txEnd(tid);
1de87444f   Ingo Molnar   JFS: semaphore to...
548
  		mutex_unlock(&JFS_IP(ip)->commit_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
  	}
  
  	if (ip->i_nlink == 0)
  		set_cflag(COMMIT_Nolink, ip);
  
  	IWRITE_UNLOCK(ip);
  
  	/*
  	 * Truncating the directory index table is not guaranteed.  It
  	 * may need to be done iteratively
  	 */
  	if (test_cflag(COMMIT_Stale, dip)) {
  		if (dip->i_size > 1)
  			jfs_truncate_nolock(dip, 0);
  
  		clear_cflag(COMMIT_Stale, dip);
  	}
  
        out1:
  	free_UCSname(&dname);
        out:
  	jfs_info("jfs_unlink: rc:%d", rc);
  	return rc;
  }
  
  /*
   * NAME:	commitZeroLink()
   *
f720e3ba5   Dave Kleikamp   JFS: Whitespace c...
577
   * FUNCTION:	for non-directory, called by jfs_remove(),
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
578
   *		truncate a regular file, directory or symbolic
63f83c9fc   Dave Kleikamp   JFS: White space ...
579
   *		link to zero length. return 0 if type is not
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
580
581
582
583
584
585
586
587
588
   *		one of these.
   *
   *		if the file is currently associated with a VM segment
   *		only permanent disk and inode map resources are freed,
   *		and neither the inode nor indirect blocks are modified
   *		so that the resources can be later freed in the work
   *		map by ctrunc1.
   *		if there is no VM segment on entry, the resources are
   *		freed in both work and permanent map.
63f83c9fc   Dave Kleikamp   JFS: White space ...
589
   *		(? for temporary file - memory object is cached even
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
   *		after no reference:
   *		reference count > 0 -   )
   *
   * PARAMETERS:	cd	- pointer to commit data structure.
   *			  current inode is the one to truncate.
   *
   * RETURN:	Errors from subroutines
   */
  static s64 commitZeroLink(tid_t tid, struct inode *ip)
  {
  	int filetype;
  	struct tblock *tblk;
  
  	jfs_info("commitZeroLink: tid = %d, ip = 0x%p", tid, ip);
  
  	filetype = ip->i_mode & S_IFMT;
  	switch (filetype) {
  	case S_IFREG:
  		break;
  	case S_IFLNK:
  		/* fast symbolic link */
  		if (ip->i_size < IDATASIZE) {
  			ip->i_size = 0;
  			return 0;
  		}
  		break;
  	default:
  		assert(filetype != S_IFDIR);
  		return 0;
  	}
  
  	set_cflag(COMMIT_Freewmap, ip);
  
  	/* mark transaction of block map update type */
  	tblk = tid_to_tblock(tid);
  	tblk->xflag |= COMMIT_PMAP;
  
  	/*
  	 * free EA
  	 */
  	if (JFS_IP(ip)->ea.flag & DXD_EXTENT)
  		/* acquire maplock on EA to be freed from block map */
  		txEA(tid, ip, &JFS_IP(ip)->ea, NULL);
  
  	/*
  	 * free ACL
  	 */
  	if (JFS_IP(ip)->acl.flag & DXD_EXTENT)
  		/* acquire maplock on EA to be freed from block map */
  		txEA(tid, ip, &JFS_IP(ip)->acl, NULL);
  
  	/*
  	 * free xtree/data (truncate to zero length):
63f83c9fc   Dave Kleikamp   JFS: White space ...
643
  	 * free xtree/data pages from cache if COMMIT_PWMAP,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
644
645
646
647
648
649
650
651
652
653
654
  	 * free xtree/data blocks from persistent block map, and
  	 * free xtree/data blocks from working block map if COMMIT_PWMAP;
  	 */
  	if (ip->i_size)
  		return xtTruncate_pmap(tid, ip, 0);
  
  	return 0;
  }
  
  
  /*
1868f4aa5   Dave Kleikamp   JFS: fix sparse w...
655
   * NAME:	jfs_free_zero_link()
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
656
   *
f720e3ba5   Dave Kleikamp   JFS: Whitespace c...
657
   * FUNCTION:	for non-directory, called by iClose(),
63f83c9fc   Dave Kleikamp   JFS: White space ...
658
   *		free resources of a file from cache and WORKING map
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
659
660
661
662
   *		for a file previously committed with zero link count
   *		while associated with a pager object,
   *
   * PARAMETER:	ip	- pointer to inode of file.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
663
   */
1868f4aa5   Dave Kleikamp   JFS: fix sparse w...
664
  void jfs_free_zero_link(struct inode *ip)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
665
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
666
  	int type;
1868f4aa5   Dave Kleikamp   JFS: fix sparse w...
667
  	jfs_info("jfs_free_zero_link: ip = 0x%p", ip);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
668
669
670
671
672
673
674
675
676
677
678
679
  
  	/* return if not reg or symbolic link or if size is
  	 * already ok.
  	 */
  	type = ip->i_mode & S_IFMT;
  
  	switch (type) {
  	case S_IFREG:
  		break;
  	case S_IFLNK:
  		/* if its contained in inode nothing to do */
  		if (ip->i_size < IDATASIZE)
1868f4aa5   Dave Kleikamp   JFS: fix sparse w...
680
  			return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
681
682
  		break;
  	default:
1868f4aa5   Dave Kleikamp   JFS: fix sparse w...
683
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
684
685
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
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
  	}
  
  	/*
  	 * free EA
  	 */
  	if (JFS_IP(ip)->ea.flag & DXD_EXTENT) {
  		s64 xaddr = addressDXD(&JFS_IP(ip)->ea);
  		int xlen = lengthDXD(&JFS_IP(ip)->ea);
  		struct maplock maplock;	/* maplock for COMMIT_WMAP */
  		struct pxd_lock *pxdlock;	/* maplock for COMMIT_WMAP */
  
  		/* free EA pages from cache */
  		invalidate_dxd_metapages(ip, JFS_IP(ip)->ea);
  
  		/* free EA extent from working block map */
  		maplock.index = 1;
  		pxdlock = (struct pxd_lock *) & maplock;
  		pxdlock->flag = mlckFREEPXD;
  		PXDaddress(&pxdlock->pxd, xaddr);
  		PXDlength(&pxdlock->pxd, xlen);
  		txFreeMap(ip, pxdlock, NULL, COMMIT_WMAP);
  	}
  
  	/*
  	 * free ACL
  	 */
  	if (JFS_IP(ip)->acl.flag & DXD_EXTENT) {
  		s64 xaddr = addressDXD(&JFS_IP(ip)->acl);
  		int xlen = lengthDXD(&JFS_IP(ip)->acl);
  		struct maplock maplock;	/* maplock for COMMIT_WMAP */
  		struct pxd_lock *pxdlock;	/* maplock for COMMIT_WMAP */
  
  		invalidate_dxd_metapages(ip, JFS_IP(ip)->acl);
  
  		/* free ACL extent from working block map */
  		maplock.index = 1;
  		pxdlock = (struct pxd_lock *) & maplock;
  		pxdlock->flag = mlckFREEPXD;
  		PXDaddress(&pxdlock->pxd, xaddr);
  		PXDlength(&pxdlock->pxd, xlen);
  		txFreeMap(ip, pxdlock, NULL, COMMIT_WMAP);
  	}
  
  	/*
  	 * free xtree/data (truncate to zero length):
  	 * free xtree/data pages from cache, and
  	 * free xtree/data blocks from working block map;
  	 */
  	if (ip->i_size)
1868f4aa5   Dave Kleikamp   JFS: fix sparse w...
733
  		xtTruncate(0, ip, 0, COMMIT_WMAP);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
734
735
736
737
738
739
740
741
  }
  
  /*
   * NAME:	jfs_link(vp, dvp, name, crp)
   *
   * FUNCTION:	create a link to <vp> by the name = <name>
   *		in the parent directory <dvp>
   *
63f83c9fc   Dave Kleikamp   JFS: White space ...
742
   * PARAMETER:	vp	- target object
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
   *		dvp	- parent directory of new link
   *		name	- name of new link to target object
   *		crp	- credential
   *
   * RETURN:	Errors from subroutines
   *
   * note:
   * JFS does NOT support link() on directories (to prevent circular
   * path in the directory hierarchy);
   * EPERM: the target object is a directory, and either the caller
   * does not have appropriate privileges or the implementation prohibits
   * using link() on directories [XPG4.2].
   *
   * JFS does NOT support links between file systems:
   * EXDEV: target object and new link are on different file systems and
   * implementation does not support links between file systems [XPG4.2].
   */
  static int jfs_link(struct dentry *old_dentry,
  	     struct inode *dir, struct dentry *dentry)
  {
  	int rc;
  	tid_t tid;
2b0143b5c   David Howells   VFS: normal files...
765
  	struct inode *ip = d_inode(old_dentry);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
766
767
768
769
  	ino_t ino;
  	struct component_name dname;
  	struct btstack btstack;
  	struct inode *iplist[2];
a455589f1   Al Viro   assorted conversi...
770
  	jfs_info("jfs_link: %pd %pd", old_dentry, dentry);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
771

acc84b05b   Dave Kleikamp   jfs: Handle error...
772
773
774
  	rc = dquot_initialize(dir);
  	if (rc)
  		goto out;
907f4554e   Christoph Hellwig   dquot: move dquot...
775

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
776
  	tid = txBegin(ip->i_sb, 0);
82d5b9a7c   Dave Kleikamp   JFS: Add lockdep ...
777
778
  	mutex_lock_nested(&JFS_IP(dir)->commit_mutex, COMMIT_MUTEX_PARENT);
  	mutex_lock_nested(&JFS_IP(ip)->commit_mutex, COMMIT_MUTEX_CHILD);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
779
780
781
782
783
  
  	/*
  	 * scan parent directory for entry/freespace
  	 */
  	if ((rc = get_UCSname(&dname, dentry)))
acc84b05b   Dave Kleikamp   jfs: Handle error...
784
  		goto out_tx;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
785
786
787
788
789
790
791
792
793
794
795
796
  
  	if ((rc = dtSearch(dir, &dname, &ino, &btstack, JFS_CREATE)))
  		goto free_dname;
  
  	/*
  	 * create entry for new link in parent directory
  	 */
  	ino = ip->i_ino;
  	if ((rc = dtInsert(tid, dir, &dname, &ino, &btstack)))
  		goto free_dname;
  
  	/* update object inode */
d8c76e6f4   Dave Hansen   [PATCH] r/o bind ...
797
  	inc_nlink(ip);		/* for new link */
078cd8279   Deepa Dinamani   fs: Replace CURRE...
798
799
  	ip->i_ctime = current_time(ip);
  	dir->i_ctime = dir->i_mtime = current_time(dir);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
800
  	mark_inode_dirty(dir);
7de9c6ee3   Al Viro   new helper: ihold()
801
  	ihold(ip);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
802
803
804
805
806
807
  
  	iplist[0] = ip;
  	iplist[1] = dir;
  	rc = txCommit(tid, 2, &iplist[0], 0);
  
  	if (rc) {
6d6b77f16   Miklos Szeredi   filesystems: add ...
808
  		drop_nlink(ip); /* never instantiated */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
809
810
811
812
813
814
  		iput(ip);
  	} else
  		d_instantiate(dentry, ip);
  
        free_dname:
  	free_UCSname(&dname);
acc84b05b   Dave Kleikamp   jfs: Handle error...
815
        out_tx:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
816
  	txEnd(tid);
1de87444f   Ingo Molnar   JFS: semaphore to...
817
  	mutex_unlock(&JFS_IP(ip)->commit_mutex);
48ce8b056   Evgeniy Dushistov   JFS: commit_mutex...
818
  	mutex_unlock(&JFS_IP(dir)->commit_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
819

acc84b05b   Dave Kleikamp   jfs: Handle error...
820
        out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
821
822
823
824
825
826
827
828
  	jfs_info("jfs_link: rc:%d", rc);
  	return rc;
  }
  
  /*
   * NAME:	jfs_symlink(dip, dentry, name)
   *
   * FUNCTION:	creates a symbolic link to <symlink> by name <name>
f720e3ba5   Dave Kleikamp   JFS: Whitespace c...
829
   *			in directory <dip>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
830
   *
f720e3ba5   Dave Kleikamp   JFS: Whitespace c...
831
832
833
834
   * PARAMETER:	dip	- parent directory vnode
   *		dentry	- dentry of symbolic link
   *		name	- the path name of the existing object
   *			  that will be the source of the link
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
   *
   * RETURN:	errors from subroutines
   *
   * note:
   * ENAMETOOLONG: pathname resolution of a symbolic link produced
   * an intermediate result whose length exceeds PATH_MAX [XPG4.2]
  */
  
  static int jfs_symlink(struct inode *dip, struct dentry *dentry,
  		const char *name)
  {
  	int rc;
  	tid_t tid;
  	ino_t ino = 0;
  	struct component_name dname;
  	int ssize;		/* source pathname size */
  	struct btstack btstack;
2b0143b5c   David Howells   VFS: normal files...
852
  	struct inode *ip = d_inode(dentry);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
853
854
  	s64 xlen = 0;
  	int bmask = 0, xsize;
3c2c22628   Dave Kleikamp   jfs: clean up som...
855
  	s64 xaddr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
856
857
858
859
860
861
862
  	struct metapage *mp;
  	struct super_block *sb;
  	struct tblock *tblk;
  
  	struct inode *iplist[2];
  
  	jfs_info("jfs_symlink: dip:0x%p name:%s", dip, name);
acc84b05b   Dave Kleikamp   jfs: Handle error...
863
864
865
  	rc = dquot_initialize(dip);
  	if (rc)
  		goto out1;
907f4554e   Christoph Hellwig   dquot: move dquot...
866

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
  	ssize = strlen(name) + 1;
  
  	/*
  	 * search parent directory for entry/freespace
  	 * (dtSearch() returns parent directory page pinned)
  	 */
  
  	if ((rc = get_UCSname(&dname, dentry)))
  		goto out1;
  
  	/*
  	 * allocate on-disk/in-memory inode for symbolic link:
  	 * (iAlloc() returns new, locked inode)
  	 */
  	ip = ialloc(dip, S_IFLNK | 0777);
087387f90   Akinobu Mita   [PATCH] JFS: retu...
882
883
  	if (IS_ERR(ip)) {
  		rc = PTR_ERR(ip);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
884
885
886
887
  		goto out2;
  	}
  
  	tid = txBegin(dip->i_sb, 0);
82d5b9a7c   Dave Kleikamp   JFS: Add lockdep ...
888
889
  	mutex_lock_nested(&JFS_IP(dip)->commit_mutex, COMMIT_MUTEX_PARENT);
  	mutex_lock_nested(&JFS_IP(ip)->commit_mutex, COMMIT_MUTEX_CHILD);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
890

2a7dba391   Eric Paris   fs/vfs/security: ...
891
  	rc = jfs_init_security(tid, ip, dip, &dentry->d_name);
1d15b10f9   Dave Kleikamp   JFS: Implement jf...
892
893
  	if (rc)
  		goto out3;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
894
895
896
897
898
899
  	tblk = tid_to_tblock(tid);
  	tblk->xflag |= COMMIT_CREATE;
  	tblk->ino = ip->i_ino;
  	tblk->u.ixpxd = JFS_IP(ip)->ixpxd;
  
  	/* fix symlink access permission
63f83c9fc   Dave Kleikamp   JFS: White space ...
900
  	 * (dir_create() ANDs in the u.u_cmask,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
901
902
903
904
905
906
907
908
909
910
911
912
913
914
  	 * but symlinks really need to be 777 access)
  	 */
  	ip->i_mode |= 0777;
  
  	/*
  	 * write symbolic link target path name
  	 */
  	xtInitRoot(tid, ip);
  
  	/*
  	 * write source path name inline in on-disk inode (fast symbolic link)
  	 */
  
  	if (ssize <= IDATASIZE) {
c7f2e1f0a   Dmitry Monakhov   jfs: add jfs spec...
915
  		ip->i_op = &jfs_fast_symlink_inode_operations;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
916

ad476fedc   Al Viro   jfs: switch to si...
917
918
  		ip->i_link = JFS_IP(ip)->i_inline;
  		memcpy(ip->i_link, name, ssize);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
  		ip->i_size = ssize - 1;
  
  		/*
  		 * if symlink is > 128 bytes, we don't have the space to
  		 * store inline extended attributes
  		 */
  		if (ssize > sizeof (JFS_IP(ip)->i_inline))
  			JFS_IP(ip)->mode2 &= ~INLINEEA;
  
  		jfs_info("jfs_symlink: fast symlink added  ssize:%d name:%s ",
  			 ssize, name);
  	}
  	/*
  	 * write source path name in a single extent
  	 */
  	else {
  		jfs_info("jfs_symlink: allocate extent ip:0x%p", ip);
c7f2e1f0a   Dmitry Monakhov   jfs: add jfs spec...
936
  		ip->i_op = &jfs_symlink_inode_operations;
21fc61c73   Al Viro   don't put symlink...
937
  		inode_nohighmem(ip);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
938
939
940
  		ip->i_mapping->a_ops = &jfs_aops;
  
  		/*
63f83c9fc   Dave Kleikamp   JFS: White space ...
941
  		 * even though the data of symlink object (source
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
942
943
944
945
946
947
948
949
950
951
  		 * path name) is treated as non-journaled user data,
  		 * it is read/written thru buffer cache for performance.
  		 */
  		sb = ip->i_sb;
  		bmask = JFS_SBI(sb)->bsize - 1;
  		xsize = (ssize + bmask) & ~bmask;
  		xaddr = 0;
  		xlen = xsize >> JFS_SBI(sb)->l2bsize;
  		if ((rc = xtInsert(tid, ip, 0, 0, xlen, &xaddr, 0))) {
  			txAbort(tid, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
952
953
  			goto out3;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
954
955
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
986
987
988
989
  		ip->i_size = ssize - 1;
  		while (ssize) {
  			/* This is kind of silly since PATH_MAX == 4K */
  			int copy_size = min(ssize, PSIZE);
  
  			mp = get_metapage(ip, xaddr, PSIZE, 1);
  
  			if (mp == NULL) {
  				xtTruncate(tid, ip, 0, COMMIT_PWMAP);
  				rc = -EIO;
  				txAbort(tid, 0);
  				goto out3;
  			}
  			memcpy(mp->data, name, copy_size);
  			flush_metapage(mp);
  			ssize -= copy_size;
  			name += copy_size;
  			xaddr += JFS_SBI(sb)->nbperpage;
  		}
  	}
  
  	/*
  	 * create entry for symbolic link in parent directory
  	 */
  	rc = dtSearch(dip, &dname, &ino, &btstack, JFS_CREATE);
  	if (rc == 0) {
  		ino = ip->i_ino;
  		rc = dtInsert(tid, dip, &dname, &ino, &btstack);
  	}
  	if (rc) {
  		if (xlen)
  			xtTruncate(tid, ip, 0, COMMIT_PWMAP);
  		txAbort(tid, 0);
  		/* discard new inode */
  		goto out3;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
990
  	mark_inode_dirty(ip);
078cd8279   Deepa Dinamani   fs: Replace CURRE...
991
  	dip->i_ctime = dip->i_mtime = current_time(dip);
988a6490a   Dave Kleikamp   JFS: set i_ctime ...
992
  	mark_inode_dirty(dip);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
993
994
995
996
997
998
999
1000
1001
1002
  	/*
  	 * commit update of parent directory and link object
  	 */
  
  	iplist[0] = dip;
  	iplist[1] = ip;
  	rc = txCommit(tid, 2, &iplist[0], 0);
  
        out3:
  	txEnd(tid);
1de87444f   Ingo Molnar   JFS: semaphore to...
1003
  	mutex_unlock(&JFS_IP(ip)->commit_mutex);
48ce8b056   Evgeniy Dushistov   JFS: commit_mutex...
1004
  	mutex_unlock(&JFS_IP(dip)->commit_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1005
  	if (rc) {
4f4b401bf   Dave Kleikamp   JFS: allow extend...
1006
  		free_ea_wmap(ip);
6d6b77f16   Miklos Szeredi   filesystems: add ...
1007
  		clear_nlink(ip);
a6cbedfa8   Al Viro   jfs: switch to di...
1008
  		discard_new_inode(ip);
1f3403fa6   Dave Kleikamp   nfsd race fixes: jfs
1009
  	} else {
1e2e547a9   Al Viro   do d_instantiate/...
1010
  		d_instantiate_new(dentry, ip);
1f3403fa6   Dave Kleikamp   nfsd race fixes: jfs
1011
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1012
1013
1014
  
        out2:
  	free_UCSname(&dname);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1015
1016
1017
1018
1019
1020
1021
        out1:
  	jfs_info("jfs_symlink: rc:%d", rc);
  	return rc;
  }
  
  
  /*
f720e3ba5   Dave Kleikamp   JFS: Whitespace c...
1022
   * NAME:	jfs_rename
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1023
   *
f720e3ba5   Dave Kleikamp   JFS: Whitespace c...
1024
   * FUNCTION:	rename a file or directory
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1025
1026
   */
  static int jfs_rename(struct inode *old_dir, struct dentry *old_dentry,
f03b8ad8d   Miklos Szeredi   fs: support RENAM...
1027
1028
  		      struct inode *new_dir, struct dentry *new_dentry,
  		      unsigned int flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
  {
  	struct btstack btstack;
  	ino_t ino;
  	struct component_name new_dname;
  	struct inode *new_ip;
  	struct component_name old_dname;
  	struct inode *old_ip;
  	int rc;
  	tid_t tid;
  	struct tlock *tlck;
  	struct dt_lock *dtlck;
  	struct lv *lv;
  	int ipcount;
  	struct inode *iplist[4];
  	struct tblock *tblk;
  	s64 new_size = 0;
  	int commit_flag;
f03b8ad8d   Miklos Szeredi   fs: support RENAM...
1046
1047
  	if (flags & ~RENAME_NOREPLACE)
  		return -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1048

a455589f1   Al Viro   assorted conversi...
1049
  	jfs_info("jfs_rename: %pd %pd", old_dentry, new_dentry);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1050

acc84b05b   Dave Kleikamp   jfs: Handle error...
1051
1052
1053
1054
1055
1056
  	rc = dquot_initialize(old_dir);
  	if (rc)
  		goto out1;
  	rc = dquot_initialize(new_dir);
  	if (rc)
  		goto out1;
907f4554e   Christoph Hellwig   dquot: move dquot...
1057

2b0143b5c   David Howells   VFS: normal files...
1058
1059
  	old_ip = d_inode(old_dentry);
  	new_ip = d_inode(new_dentry);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
  
  	if ((rc = get_UCSname(&old_dname, old_dentry)))
  		goto out1;
  
  	if ((rc = get_UCSname(&new_dname, new_dentry)))
  		goto out2;
  
  	/*
  	 * Make sure source inode number is what we think it is
  	 */
  	rc = dtSearch(old_dir, &old_dname, &ino, &btstack, JFS_LOOKUP);
  	if (rc || (ino != old_ip->i_ino)) {
  		rc = -ENOENT;
  		goto out3;
  	}
  
  	/*
  	 * Make sure dest inode number (if any) is what we think it is
  	 */
  	rc = dtSearch(new_dir, &new_dname, &ino, &btstack, JFS_LOOKUP);
09aaa749f   Joe Perches   JFS: Remove defco...
1080
  	if (!rc) {
da8a41d19   Dave Kleikamp   JFS: FIx one more...
1081
  		if ((!new_ip) || (ino != new_ip->i_ino)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
  			rc = -ESTALE;
  			goto out3;
  		}
  	} else if (rc != -ENOENT)
  		goto out3;
  	else if (new_ip) {
  		/* no entry exists, but one was expected */
  		rc = -ESTALE;
  		goto out3;
  	}
  
  	if (S_ISDIR(old_ip->i_mode)) {
  		if (new_ip) {
  			if (!dtEmpty(new_ip)) {
  				rc = -ENOTEMPTY;
  				goto out3;
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1099
1100
  		}
  	} else if (new_ip) {
82d5b9a7c   Dave Kleikamp   JFS: Add lockdep ...
1101
  		IWRITE_LOCK(new_ip, RDWRLOCK_NORMAL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1102
  		/* Init inode for quota operations. */
acc84b05b   Dave Kleikamp   jfs: Handle error...
1103
1104
1105
  		rc = dquot_initialize(new_ip);
  		if (rc)
  			goto out_unlock;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1106
1107
1108
1109
1110
1111
  	}
  
  	/*
  	 * The real work starts here
  	 */
  	tid = txBegin(new_dir->i_sb, 0);
82d5b9a7c   Dave Kleikamp   JFS: Add lockdep ...
1112
1113
1114
1115
1116
1117
1118
1119
  	/*
  	 * How do we know the locking is safe from deadlocks?
  	 * The vfs does the hard part for us.  Any time we are taking nested
  	 * commit_mutexes, the vfs already has i_mutex held on the parent.
  	 * Here, the vfs has already taken i_mutex on both old_dir and new_dir.
  	 */
  	mutex_lock_nested(&JFS_IP(new_dir)->commit_mutex, COMMIT_MUTEX_PARENT);
  	mutex_lock_nested(&JFS_IP(old_ip)->commit_mutex, COMMIT_MUTEX_CHILD);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1120
  	if (old_dir != new_dir)
82d5b9a7c   Dave Kleikamp   JFS: Add lockdep ...
1121
1122
  		mutex_lock_nested(&JFS_IP(old_dir)->commit_mutex,
  				  COMMIT_MUTEX_SECOND_PARENT);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1123
1124
  
  	if (new_ip) {
82d5b9a7c   Dave Kleikamp   JFS: Add lockdep ...
1125
1126
  		mutex_lock_nested(&JFS_IP(new_ip)->commit_mutex,
  				  COMMIT_MUTEX_VICTIM);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1127
1128
1129
1130
1131
1132
1133
  		/*
  		 * Change existing directory entry to new inode number
  		 */
  		ino = new_ip->i_ino;
  		rc = dtModify(tid, new_dir, &new_dname, &ino,
  			      old_ip->i_ino, JFS_RENAME);
  		if (rc)
264569557   Dave Kleikamp   jfs: clean up jfs...
1134
  			goto out_tx;
9a53c3a78   Dave Hansen   [PATCH] r/o bind ...
1135
  		drop_nlink(new_ip);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1136
  		if (S_ISDIR(new_ip->i_mode)) {
9a53c3a78   Dave Hansen   [PATCH] r/o bind ...
1137
  			drop_nlink(new_ip);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1138
  			if (new_ip->i_nlink) {
48ce8b056   Evgeniy Dushistov   JFS: commit_mutex...
1139
  				mutex_unlock(&JFS_IP(new_ip)->commit_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1140
  				if (old_dir != new_dir)
1de87444f   Ingo Molnar   JFS: semaphore to...
1141
  					mutex_unlock(&JFS_IP(old_dir)->commit_mutex);
48ce8b056   Evgeniy Dushistov   JFS: commit_mutex...
1142
1143
  				mutex_unlock(&JFS_IP(old_ip)->commit_mutex);
  				mutex_unlock(&JFS_IP(new_dir)->commit_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1144
1145
1146
  				if (!S_ISDIR(old_ip->i_mode) && new_ip)
  					IWRITE_UNLOCK(new_ip);
  				jfs_error(new_ip->i_sb,
eb8630d7d   Joe Perches   jfs: Update jfs_e...
1147
1148
  					  "new_ip->i_nlink != 0
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
  				return -EIO;
  			}
  			tblk = tid_to_tblock(tid);
  			tblk->xflag |= COMMIT_DELETE;
  			tblk->u.ip = new_ip;
  		} else if (new_ip->i_nlink == 0) {
  			assert(!test_cflag(COMMIT_Nolink, new_ip));
  			/* free block resources */
  			if ((new_size = commitZeroLink(tid, new_ip)) < 0) {
  				txAbort(tid, 1);	/* Marks FS Dirty */
63f83c9fc   Dave Kleikamp   JFS: White space ...
1159
  				rc = new_size;
264569557   Dave Kleikamp   jfs: clean up jfs...
1160
  				goto out_tx;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1161
1162
1163
1164
1165
  			}
  			tblk = tid_to_tblock(tid);
  			tblk->xflag |= COMMIT_DELETE;
  			tblk->u.ip = new_ip;
  		} else {
078cd8279   Deepa Dinamani   fs: Replace CURRE...
1166
  			new_ip->i_ctime = current_time(new_ip);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1167
1168
1169
1170
1171
1172
1173
1174
1175
  			mark_inode_dirty(new_ip);
  		}
  	} else {
  		/*
  		 * Add new directory entry
  		 */
  		rc = dtSearch(new_dir, &new_dname, &ino, &btstack,
  			      JFS_CREATE);
  		if (rc) {
6ed71e981   Joe Perches   jfs: Coalesce som...
1176
1177
  			jfs_err("jfs_rename didn't expect dtSearch to fail w/rc = %d",
  				rc);
264569557   Dave Kleikamp   jfs: clean up jfs...
1178
  			goto out_tx;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1179
1180
1181
1182
1183
1184
1185
  		}
  
  		ino = old_ip->i_ino;
  		rc = dtInsert(tid, new_dir, &new_dname, &ino, &btstack);
  		if (rc) {
  			if (rc == -EIO)
  				jfs_err("jfs_rename: dtInsert returned -EIO");
264569557   Dave Kleikamp   jfs: clean up jfs...
1186
  			goto out_tx;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1187
1188
  		}
  		if (S_ISDIR(old_ip->i_mode))
d8c76e6f4   Dave Hansen   [PATCH] r/o bind ...
1189
  			inc_nlink(new_dir);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
  	}
  	/*
  	 * Remove old directory entry
  	 */
  
  	ino = old_ip->i_ino;
  	rc = dtDelete(tid, old_dir, &old_dname, &ino, JFS_REMOVE);
  	if (rc) {
  		jfs_err("jfs_rename did not expect dtDelete to return rc = %d",
  			rc);
  		txAbort(tid, 1);	/* Marks Filesystem dirty */
264569557   Dave Kleikamp   jfs: clean up jfs...
1201
  		goto out_tx;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1202
1203
  	}
  	if (S_ISDIR(old_ip->i_mode)) {
9a53c3a78   Dave Hansen   [PATCH] r/o bind ...
1204
  		drop_nlink(old_dir);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
  		if (old_dir != new_dir) {
  			/*
  			 * Change inode number of parent for moved directory
  			 */
  
  			JFS_IP(old_ip)->i_dtroot.header.idotdot =
  				cpu_to_le32(new_dir->i_ino);
  
  			/* Linelock header of dtree */
  			tlck = txLock(tid, old_ip,
  				    (struct metapage *) &JFS_IP(old_ip)->bxflag,
  				      tlckDTREE | tlckBTROOT | tlckRELINK);
  			dtlck = (struct dt_lock *) & tlck->lock;
  			ASSERT(dtlck->index == 0);
  			lv = & dtlck->lv[0];
  			lv->offset = 0;
  			lv->length = 1;
  			dtlck->index++;
  		}
  	}
  
  	/*
  	 * Update ctime on changed/moved inodes & mark dirty
  	 */
078cd8279   Deepa Dinamani   fs: Replace CURRE...
1229
  	old_ip->i_ctime = current_time(old_ip);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1230
  	mark_inode_dirty(old_ip);
c2050a454   Deepa Dinamani   fs: Replace curre...
1231
  	new_dir->i_ctime = new_dir->i_mtime = current_time(new_dir);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
  	mark_inode_dirty(new_dir);
  
  	/* Build list of inodes modified by this transaction */
  	ipcount = 0;
  	iplist[ipcount++] = old_ip;
  	if (new_ip)
  		iplist[ipcount++] = new_ip;
  	iplist[ipcount++] = old_dir;
  
  	if (old_dir != new_dir) {
  		iplist[ipcount++] = new_dir;
078cd8279   Deepa Dinamani   fs: Replace CURRE...
1243
  		old_dir->i_ctime = old_dir->i_mtime = current_time(old_dir);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
  		mark_inode_dirty(old_dir);
  	}
  
  	/*
  	 * Incomplete truncate of file data can
  	 * result in timing problems unless we synchronously commit the
  	 * transaction.
  	 */
  	if (new_size)
  		commit_flag = COMMIT_SYNC;
  	else
  		commit_flag = 0;
  
  	rc = txCommit(tid, ipcount, iplist, commit_flag);
264569557   Dave Kleikamp   jfs: clean up jfs...
1258
        out_tx:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1259
  	txEnd(tid);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1260
  	if (new_ip)
1de87444f   Ingo Molnar   JFS: semaphore to...
1261
  		mutex_unlock(&JFS_IP(new_ip)->commit_mutex);
48ce8b056   Evgeniy Dushistov   JFS: commit_mutex...
1262
1263
1264
1265
  	if (old_dir != new_dir)
  		mutex_unlock(&JFS_IP(old_dir)->commit_mutex);
  	mutex_unlock(&JFS_IP(old_ip)->commit_mutex);
  	mutex_unlock(&JFS_IP(new_dir)->commit_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1266
1267
1268
  
  	while (new_size && (rc == 0)) {
  		tid = txBegin(new_ip->i_sb, 0);
1de87444f   Ingo Molnar   JFS: semaphore to...
1269
  		mutex_lock(&JFS_IP(new_ip)->commit_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1270
1271
1272
  		new_size = xtTruncate_pmap(tid, new_ip, new_size);
  		if (new_size < 0) {
  			txAbort(tid, 1);
63f83c9fc   Dave Kleikamp   JFS: White space ...
1273
  			rc = new_size;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1274
1275
1276
  		} else
  			rc = txCommit(tid, 1, &new_ip, COMMIT_SYNC);
  		txEnd(tid);
1de87444f   Ingo Molnar   JFS: semaphore to...
1277
  		mutex_unlock(&JFS_IP(new_ip)->commit_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1278
1279
1280
  	}
  	if (new_ip && (new_ip->i_nlink == 0))
  		set_cflag(COMMIT_Nolink, new_ip);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
  	/*
  	 * Truncating the directory index table is not guaranteed.  It
  	 * may need to be done iteratively
  	 */
  	if (test_cflag(COMMIT_Stale, old_dir)) {
  		if (old_dir->i_size > 1)
  			jfs_truncate_nolock(old_dir, 0);
  
  		clear_cflag(COMMIT_Stale, old_dir);
  	}
acc84b05b   Dave Kleikamp   jfs: Handle error...
1291
        out_unlock:
264569557   Dave Kleikamp   jfs: clean up jfs...
1292
1293
1294
1295
1296
1297
1298
  	if (new_ip && !S_ISDIR(new_ip->i_mode))
  		IWRITE_UNLOCK(new_ip);
        out3:
  	free_UCSname(&new_dname);
        out2:
  	free_UCSname(&old_dname);
        out1:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1299
1300
1301
1302
1303
1304
  	jfs_info("jfs_rename: returning %d", rc);
  	return rc;
  }
  
  
  /*
f720e3ba5   Dave Kleikamp   JFS: Whitespace c...
1305
   * NAME:	jfs_mknod
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1306
   *
f720e3ba5   Dave Kleikamp   JFS: Whitespace c...
1307
   * FUNCTION:	Create a special file (device)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1308
1309
   */
  static int jfs_mknod(struct inode *dir, struct dentry *dentry,
1a67aafb5   Al Viro   switch ->mknod() ...
1310
  		umode_t mode, dev_t rdev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
  {
  	struct jfs_inode_info *jfs_ip;
  	struct btstack btstack;
  	struct component_name dname;
  	ino_t ino;
  	struct inode *ip;
  	struct inode *iplist[2];
  	int rc;
  	tid_t tid;
  	struct tblock *tblk;
a455589f1   Al Viro   assorted conversi...
1321
  	jfs_info("jfs_mknod: %pd", dentry);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1322

acc84b05b   Dave Kleikamp   jfs: Handle error...
1323
1324
1325
  	rc = dquot_initialize(dir);
  	if (rc)
  		goto out;
907f4554e   Christoph Hellwig   dquot: move dquot...
1326

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1327
1328
1329
1330
  	if ((rc = get_UCSname(&dname, dentry)))
  		goto out;
  
  	ip = ialloc(dir, mode);
087387f90   Akinobu Mita   [PATCH] JFS: retu...
1331
1332
  	if (IS_ERR(ip)) {
  		rc = PTR_ERR(ip);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1333
1334
1335
1336
1337
  		goto out1;
  	}
  	jfs_ip = JFS_IP(ip);
  
  	tid = txBegin(dir->i_sb, 0);
82d5b9a7c   Dave Kleikamp   JFS: Add lockdep ...
1338
1339
  	mutex_lock_nested(&JFS_IP(dir)->commit_mutex, COMMIT_MUTEX_PARENT);
  	mutex_lock_nested(&JFS_IP(ip)->commit_mutex, COMMIT_MUTEX_CHILD);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1340

4f4b401bf   Dave Kleikamp   JFS: allow extend...
1341
1342
  	rc = jfs_init_acl(tid, ip, dir);
  	if (rc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1343
  		goto out3;
2a7dba391   Eric Paris   fs/vfs/security: ...
1344
  	rc = jfs_init_security(tid, ip, dir, &dentry->d_name);
1d15b10f9   Dave Kleikamp   JFS: Implement jf...
1345
1346
1347
1348
  	if (rc) {
  		txAbort(tid, 0);
  		goto out3;
  	}
4f4b401bf   Dave Kleikamp   JFS: allow extend...
1349
1350
1351
1352
  	if ((rc = dtSearch(dir, &dname, &ino, &btstack, JFS_CREATE))) {
  		txAbort(tid, 0);
  		goto out3;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1353
1354
1355
1356
1357
1358
  	tblk = tid_to_tblock(tid);
  	tblk->xflag |= COMMIT_CREATE;
  	tblk->ino = ip->i_ino;
  	tblk->u.ixpxd = JFS_IP(ip)->ixpxd;
  
  	ino = ip->i_ino;
4f4b401bf   Dave Kleikamp   JFS: allow extend...
1359
1360
  	if ((rc = dtInsert(tid, dir, &dname, &ino, &btstack))) {
  		txAbort(tid, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1361
  		goto out3;
4f4b401bf   Dave Kleikamp   JFS: allow extend...
1362
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1363
1364
1365
1366
  
  	ip->i_op = &jfs_file_inode_operations;
  	jfs_ip->dev = new_encode_dev(rdev);
  	init_special_inode(ip, ip->i_mode, rdev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1367
  	mark_inode_dirty(ip);
078cd8279   Deepa Dinamani   fs: Replace CURRE...
1368
  	dir->i_ctime = dir->i_mtime = current_time(dir);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1369
1370
1371
1372
1373
1374
1375
1376
1377
  
  	mark_inode_dirty(dir);
  
  	iplist[0] = dir;
  	iplist[1] = ip;
  	rc = txCommit(tid, 2, iplist, 0);
  
        out3:
  	txEnd(tid);
1de87444f   Ingo Molnar   JFS: semaphore to...
1378
1379
  	mutex_unlock(&JFS_IP(ip)->commit_mutex);
  	mutex_unlock(&JFS_IP(dir)->commit_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1380
  	if (rc) {
4f4b401bf   Dave Kleikamp   JFS: allow extend...
1381
  		free_ea_wmap(ip);
6d6b77f16   Miklos Szeredi   filesystems: add ...
1382
  		clear_nlink(ip);
a6cbedfa8   Al Viro   jfs: switch to di...
1383
  		discard_new_inode(ip);
1f3403fa6   Dave Kleikamp   nfsd race fixes: jfs
1384
  	} else {
1e2e547a9   Al Viro   do d_instantiate/...
1385
  		d_instantiate_new(dentry, ip);
1f3403fa6   Dave Kleikamp   nfsd race fixes: jfs
1386
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1387
1388
1389
  
        out1:
  	free_UCSname(&dname);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1390
1391
1392
1393
        out:
  	jfs_info("jfs_mknod: returning %d", rc);
  	return rc;
  }
00cd8dd3b   Al Viro   stop passing name...
1394
  static struct dentry *jfs_lookup(struct inode *dip, struct dentry *dentry, unsigned int flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1395
1396
1397
1398
1399
  {
  	struct btstack btstack;
  	ino_t inum;
  	struct inode *ip;
  	struct component_name key;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1400
  	int rc;
a455589f1   Al Viro   assorted conversi...
1401
  	jfs_info("jfs_lookup: name = %pd", dentry);
79ac5a46c   Al Viro   jfs_lookup(): don...
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
  
  	if ((rc = get_UCSname(&key, dentry)))
  		return ERR_PTR(rc);
  	rc = dtSearch(dip, &key, &inum, &btstack, JFS_LOOKUP);
  	free_UCSname(&key);
  	if (rc == -ENOENT) {
  		ip = NULL;
  	} else if (rc) {
  		jfs_err("jfs_lookup: dtSearch returned %d", rc);
  		ip = ERR_PTR(rc);
  	} else {
  		ip = jfs_iget(dip->i_sb, inum);
  		if (IS_ERR(ip))
  			jfs_err("jfs_lookup: iget failed on inum %d", (uint)inum);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1416
  	}
94b77bd86   Al Viro   switch jfs to ->s...
1417
  	return d_splice_alias(ip, dentry);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1418
  }
d425de704   Christoph Hellwig   jfs: new export ops
1419
1420
  static struct inode *jfs_nfs_get_inode(struct super_block *sb,
  		u64 ino, u32 generation)
5ca296073   Christoph Hellwig   knfsd: exportfs: ...
1421
  {
5ca296073   Christoph Hellwig   knfsd: exportfs: ...
1422
  	struct inode *inode;
5ca296073   Christoph Hellwig   knfsd: exportfs: ...
1423
1424
1425
  
  	if (ino == 0)
  		return ERR_PTR(-ESTALE);
eab1df71a   David Howells   iget: stop JFS fr...
1426
1427
1428
  	inode = jfs_iget(sb, ino);
  	if (IS_ERR(inode))
  		return ERR_CAST(inode);
5ca296073   Christoph Hellwig   knfsd: exportfs: ...
1429

eab1df71a   David Howells   iget: stop JFS fr...
1430
  	if (generation && inode->i_generation != generation) {
d425de704   Christoph Hellwig   jfs: new export ops
1431
1432
  		iput(inode);
  		return ERR_PTR(-ESTALE);
5ca296073   Christoph Hellwig   knfsd: exportfs: ...
1433
  	}
d425de704   Christoph Hellwig   jfs: new export ops
1434
1435
  	return inode;
  }
5ca296073   Christoph Hellwig   knfsd: exportfs: ...
1436

d425de704   Christoph Hellwig   jfs: new export ops
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
  struct dentry *jfs_fh_to_dentry(struct super_block *sb, struct fid *fid,
  		int fh_len, int fh_type)
  {
  	return generic_fh_to_dentry(sb, fid, fh_len, fh_type,
  				    jfs_nfs_get_inode);
  }
  
  struct dentry *jfs_fh_to_parent(struct super_block *sb, struct fid *fid,
  		int fh_len, int fh_type)
  {
  	return generic_fh_to_parent(sb, fid, fh_len, fh_type,
  				    jfs_nfs_get_inode);
5ca296073   Christoph Hellwig   knfsd: exportfs: ...
1449
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1450
1451
  struct dentry *jfs_get_parent(struct dentry *dentry)
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1452
1453
1454
  	unsigned long parent_ino;
  
  	parent_ino =
2b0143b5c   David Howells   VFS: normal files...
1455
  		le32_to_cpu(JFS_IP(d_inode(dentry))->i_dtroot.header.idotdot);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1456

fc64005c9   Al Viro   don't bother with...
1457
  	return d_obtain_alias(jfs_iget(dentry->d_sb, parent_ino));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1458
  }
92e1d5be9   Arjan van de Ven   [PATCH] mark stru...
1459
  const struct inode_operations jfs_dir_inode_operations = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1460
1461
1462
1463
1464
1465
1466
1467
1468
  	.create		= jfs_create,
  	.lookup		= jfs_lookup,
  	.link		= jfs_link,
  	.unlink		= jfs_unlink,
  	.symlink	= jfs_symlink,
  	.mkdir		= jfs_mkdir,
  	.rmdir		= jfs_rmdir,
  	.mknod		= jfs_mknod,
  	.rename		= jfs_rename,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1469
  	.listxattr	= jfs_listxattr,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1470
  	.setattr	= jfs_setattr,
759bfee65   Christoph Hellwig   dquot: move dquot...
1471
  #ifdef CONFIG_JFS_POSIX_ACL
4e34e719e   Christoph Hellwig   fs: take the ACL ...
1472
  	.get_acl	= jfs_get_acl,
2cc6a5a01   Christoph Hellwig   jfs: use generic ...
1473
  	.set_acl	= jfs_set_acl,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1474
1475
  #endif
  };
4b6f5d20b   Arjan van de Ven   [PATCH] Make most...
1476
  const struct file_operations jfs_dir_operations = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1477
  	.read		= generic_read_dir,
070a0ebf4   Al Viro   [readdir] convert...
1478
  	.iterate	= jfs_readdir,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1479
  	.fsync		= jfs_fsync,
baab81fa5   Andi Kleen   BKL-removal: Use ...
1480
  	.unlocked_ioctl = jfs_ioctl,
ef1fc2f01   Andi Kleen   BKL-removal: Impl...
1481
1482
1483
  #ifdef CONFIG_COMPAT
  	.compat_ioctl	= jfs_compat_ioctl,
  #endif
3222a3e55   Christoph Hellwig   [PATCH] fix ->lls...
1484
  	.llseek		= generic_file_llseek,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1485
  };
da53be12b   Linus Torvalds   Don't pass inode ...
1486
  static int jfs_ci_hash(const struct dentry *dir, struct qstr *this)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1487
1488
1489
  {
  	unsigned long hash;
  	int i;
8387ff257   Linus Torvalds   vfs: make the str...
1490
  	hash = init_name_hash(dir);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1491
1492
1493
1494
1495
1496
  	for (i=0; i < this->len; i++)
  		hash = partial_name_hash(tolower(this->name[i]), hash);
  	this->hash = end_name_hash(hash);
  
  	return 0;
  }
6fa67e707   Al Viro   get rid of 'paren...
1497
  static int jfs_ci_compare(const struct dentry *dentry,
621e155a3   Nick Piggin   fs: change d_comp...
1498
  		unsigned int len, const char *str, const struct qstr *name)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1499
1500
  {
  	int i, result = 1;
621e155a3   Nick Piggin   fs: change d_comp...
1501
  	if (len != name->len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1502
  		goto out;
621e155a3   Nick Piggin   fs: change d_comp...
1503
1504
  	for (i=0; i < len; i++) {
  		if (tolower(str[i]) != tolower(name->name[i]))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1505
1506
1507
  			goto out;
  	}
  	result = 0;
2bc334dcc   Nick Piggin   jfs: dont overwri...
1508
1509
1510
  out:
  	return result;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1511

0b728e191   Al Viro   stop passing name...
1512
  static int jfs_ci_revalidate(struct dentry *dentry, unsigned int flags)
2bc334dcc   Nick Piggin   jfs: dont overwri...
1513
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1514
  	/*
2bc334dcc   Nick Piggin   jfs: dont overwri...
1515
1516
1517
1518
1519
1520
1521
1522
  	 * This is not negative dentry. Always valid.
  	 *
  	 * Note, rename() to existing directory entry will have ->d_inode,
  	 * and will use existing name which isn't specified name by user.
  	 *
  	 * We may be able to drop this positive dentry here. But dropping
  	 * positive dentry isn't good idea. So it's unsupported like
  	 * rename("filename", "FILENAME") for now.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1523
  	 */
2b0143b5c   David Howells   VFS: normal files...
1524
  	if (d_really_is_positive(dentry))
2bc334dcc   Nick Piggin   jfs: dont overwri...
1525
1526
1527
1528
1529
1530
  		return 1;
  
  	/*
  	 * This may be nfsd (or something), anyway, we can't see the
  	 * intent of this. So, since this can be for creation, drop it.
  	 */
0b728e191   Al Viro   stop passing name...
1531
  	if (!flags)
2bc334dcc   Nick Piggin   jfs: dont overwri...
1532
1533
1534
1535
1536
1537
1538
  		return 0;
  
  	/*
  	 * Drop the negative dentry, in order to make sure to use the
  	 * case sensitive name which is specified by user if this is
  	 * for creation.
  	 */
0b728e191   Al Viro   stop passing name...
1539
  	if (flags & (LOOKUP_CREATE | LOOKUP_RENAME_TARGET))
407938e79   Al Viro   LOOKUP_CREATE and...
1540
  		return 0;
2bc334dcc   Nick Piggin   jfs: dont overwri...
1541
  	return 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1542
  }
ad28b4ef1   Al Viro   constify dentry_o...
1543
  const struct dentry_operations jfs_ci_dentry_operations =
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1544
1545
1546
  {
  	.d_hash = jfs_ci_hash,
  	.d_compare = jfs_ci_compare,
2bc334dcc   Nick Piggin   jfs: dont overwri...
1547
  	.d_revalidate = jfs_ci_revalidate,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1548
  };