Blame view

fs/udf/namei.c 32.8 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
  /*
   * namei.c
   *
   * PURPOSE
   *      Inode name handling routines for the OSTA-UDF(tm) filesystem.
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
   * COPYRIGHT
   *      This file is distributed under the terms of the GNU General Public
   *      License (GPL). Copies of the GPL can be obtained from:
   *              ftp://prep.ai.mit.edu/pub/gnu/GPL
   *      Each contributing author retains all rights to their own work.
   *
   *  (C) 1998-2004 Ben Fennema
   *  (C) 1999-2000 Stelias Computing Inc
   *
   * HISTORY
   *
   *  12/12/98 blf  Created. Split out the lookup code from dir.c
   *  04/19/99 blf  link, mknod, symlink support
   */
  
  #include "udfdecl.h"
  
  #include "udf_i.h"
  #include "udf_sb.h"
  #include <linux/string.h>
  #include <linux/errno.h>
  #include <linux/mm.h>
  #include <linux/slab.h>
  #include <linux/quotaops.h>
  #include <linux/smp_lock.h>
  #include <linux/buffer_head.h>
e8edc6e03   Alexey Dobriyan   Detach sched.h fr...
33
  #include <linux/sched.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
34

cb00ea352   Cyrill Gorcunov   UDF: coding style...
35
36
  static inline int udf_match(int len1, const char *name1, int len2,
  			    const char *name2)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
37
38
39
40
41
42
43
  {
  	if (len1 != len2)
  		return 0;
  	return !memcmp(name1, name2, len1);
  }
  
  int udf_write_fi(struct inode *inode, struct fileIdentDesc *cfi,
cb00ea352   Cyrill Gorcunov   UDF: coding style...
44
45
  		 struct fileIdentDesc *sfi, struct udf_fileident_bh *fibh,
  		 uint8_t * impuse, uint8_t * fileident)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
46
47
48
49
50
51
52
53
54
  {
  	uint16_t crclen = fibh->eoffset - fibh->soffset - sizeof(tag);
  	uint16_t crc;
  	uint8_t checksum = 0;
  	int i;
  	int offset;
  	uint16_t liu = le16_to_cpu(cfi->lengthOfImpUse);
  	uint8_t lfi = cfi->lengthFileIdent;
  	int padlen = fibh->eoffset - fibh->soffset - liu - lfi -
cb00ea352   Cyrill Gorcunov   UDF: coding style...
55
  	    sizeof(struct fileIdentDesc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
56
57
58
59
60
61
  	int adinicb = 0;
  
  	if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_IN_ICB)
  		adinicb = 1;
  
  	offset = fibh->soffset + sizeof(struct fileIdentDesc);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
62
  	if (impuse) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
63
  		if (adinicb || (offset + liu < 0))
cb00ea352   Cyrill Gorcunov   UDF: coding style...
64
  			memcpy((uint8_t *) sfi->impUse, impuse, liu);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
65
66
  		else if (offset >= 0)
  			memcpy(fibh->ebh->b_data + offset, impuse, liu);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
67
68
69
70
  		else {
  			memcpy((uint8_t *) sfi->impUse, impuse, -offset);
  			memcpy(fibh->ebh->b_data, impuse - offset,
  			       liu + offset);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
71
72
73
74
  		}
  	}
  
  	offset += liu;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
75
  	if (fileident) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
76
  		if (adinicb || (offset + lfi < 0))
cb00ea352   Cyrill Gorcunov   UDF: coding style...
77
78
  			memcpy((uint8_t *) sfi->fileIdent + liu, fileident,
  			       lfi);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
79
80
  		else if (offset >= 0)
  			memcpy(fibh->ebh->b_data + offset, fileident, lfi);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
81
82
83
84
85
  		else {
  			memcpy((uint8_t *) sfi->fileIdent + liu, fileident,
  			       -offset);
  			memcpy(fibh->ebh->b_data, fileident - offset,
  			       lfi + offset);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
86
87
88
89
90
91
  		}
  	}
  
  	offset += lfi;
  
  	if (adinicb || (offset + padlen < 0))
cb00ea352   Cyrill Gorcunov   UDF: coding style...
92
  		memset((uint8_t *) sfi->padding + liu + lfi, 0x00, padlen);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
93
94
  	else if (offset >= 0)
  		memset(fibh->ebh->b_data + offset, 0x00, padlen);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
95
96
  	else {
  		memset((uint8_t *) sfi->padding + liu + lfi, 0x00, -offset);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
97
98
  		memset(fibh->ebh->b_data, 0x00, padlen + offset);
  	}
cb00ea352   Cyrill Gorcunov   UDF: coding style...
99
100
101
  	crc =
  	    udf_crc((uint8_t *) cfi + sizeof(tag),
  		    sizeof(struct fileIdentDesc) - sizeof(tag), 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
102
103
  
  	if (fibh->sbh == fibh->ebh)
cb00ea352   Cyrill Gorcunov   UDF: coding style...
104
105
106
  		crc = udf_crc((uint8_t *) sfi->impUse,
  			      crclen + sizeof(tag) -
  			      sizeof(struct fileIdentDesc), crc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
107
  	else if (sizeof(struct fileIdentDesc) >= -fibh->soffset)
cb00ea352   Cyrill Gorcunov   UDF: coding style...
108
109
110
111
112
113
114
115
116
  		crc =
  		    udf_crc(fibh->ebh->b_data + sizeof(struct fileIdentDesc) +
  			    fibh->soffset,
  			    crclen + sizeof(tag) - sizeof(struct fileIdentDesc),
  			    crc);
  	else {
  		crc = udf_crc((uint8_t *) sfi->impUse,
  			      -fibh->soffset - sizeof(struct fileIdentDesc),
  			      crc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
117
118
119
120
121
  		crc = udf_crc(fibh->ebh->b_data, fibh->eoffset, crc);
  	}
  
  	cfi->descTag.descCRC = cpu_to_le16(crc);
  	cfi->descTag.descCRCLength = cpu_to_le16(crclen);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
122
  	for (i = 0; i < 16; i++)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
123
  		if (i != 4)
cb00ea352   Cyrill Gorcunov   UDF: coding style...
124
  			checksum += ((uint8_t *) & cfi->descTag)[i];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
125
126
127
  
  	cfi->descTag.tagChecksum = checksum;
  	if (adinicb || (sizeof(struct fileIdentDesc) <= -fibh->soffset))
cb00ea352   Cyrill Gorcunov   UDF: coding style...
128
129
130
131
132
133
  		memcpy((uint8_t *) sfi, (uint8_t *) cfi,
  		       sizeof(struct fileIdentDesc));
  	else {
  		memcpy((uint8_t *) sfi, (uint8_t *) cfi, -fibh->soffset);
  		memcpy(fibh->ebh->b_data, (uint8_t *) cfi - fibh->soffset,
  		       sizeof(struct fileIdentDesc) + fibh->soffset);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
134
135
136
137
  	}
  
  	if (adinicb)
  		mark_inode_dirty(inode);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
138
  	else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
139
140
141
142
143
144
  		if (fibh->sbh != fibh->ebh)
  			mark_buffer_dirty_inode(fibh->ebh, inode);
  		mark_buffer_dirty_inode(fibh->sbh, inode);
  	}
  	return 0;
  }
cb00ea352   Cyrill Gorcunov   UDF: coding style...
145
146
147
148
  static struct fileIdentDesc *udf_find_entry(struct inode *dir,
  					    struct dentry *dentry,
  					    struct udf_fileident_bh *fibh,
  					    struct fileIdentDesc *cfi)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
149
  {
cb00ea352   Cyrill Gorcunov   UDF: coding style...
150
  	struct fileIdentDesc *fi = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
151
152
153
154
155
156
  	loff_t f_pos;
  	int block, flen;
  	char fname[UDF_NAME_LEN];
  	char *nameptr;
  	uint8_t lfi;
  	uint16_t liu;
ec471dc48   KAMBAROV, ZAUR   [PATCH] coverity:...
157
  	loff_t size;
ff116fc8d   Jan Kara   UDF: introduce st...
158
159
  	kernel_lb_addr eloc;
  	uint32_t elen;
60448b1d6   Jan Kara   udf: use sector_t...
160
  	sector_t offset;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
161
  	struct extent_position epos = { NULL, 0, {0, 0} };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
162

ec471dc48   KAMBAROV, ZAUR   [PATCH] coverity:...
163
  	size = (udf_ext0_offset(dir) + dir->i_size) >> 2;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
164
  	f_pos = (udf_ext0_offset(dir) >> 2);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
165
166
  	fibh->soffset = fibh->eoffset =
  	    (f_pos & ((dir->i_sb->s_blocksize - 1) >> 2)) << 2;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
167
168
169
  	if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB)
  		fibh->sbh = fibh->ebh = NULL;
  	else if (inode_bmap(dir, f_pos >> (dir->i_sb->s_blocksize_bits - 2),
cb00ea352   Cyrill Gorcunov   UDF: coding style...
170
171
  			    &epos, &eloc, &elen,
  			    &offset) == (EXT_RECORDED_ALLOCATED >> 30)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
172
  		block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
173
  		if ((++offset << dir->i_sb->s_blocksize_bits) < elen) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
174
  			if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_SHORT)
ff116fc8d   Jan Kara   UDF: introduce st...
175
  				epos.offset -= sizeof(short_ad);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
176
  			else if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_LONG)
ff116fc8d   Jan Kara   UDF: introduce st...
177
  				epos.offset -= sizeof(long_ad);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
178
  		} else
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
179
  			offset = 0;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
180
  		if (!(fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block))) {
3bf25cb40   Jan Kara   udf: use get_bh()
181
  			brelse(epos.bh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
182
183
  			return NULL;
  		}
cb00ea352   Cyrill Gorcunov   UDF: coding style...
184
  	} else {
3bf25cb40   Jan Kara   udf: use get_bh()
185
  		brelse(epos.bh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
186
187
  		return NULL;
  	}
cb00ea352   Cyrill Gorcunov   UDF: coding style...
188
189
190
  	while ((f_pos < size)) {
  		fi = udf_fileident_read(dir, &f_pos, fibh, cfi, &epos, &eloc,
  					&elen, &offset);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
191

cb00ea352   Cyrill Gorcunov   UDF: coding style...
192
  		if (!fi) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
193
  			if (fibh->sbh != fibh->ebh)
3bf25cb40   Jan Kara   udf: use get_bh()
194
195
196
  				brelse(fibh->ebh);
  			brelse(fibh->sbh);
  			brelse(epos.bh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
197
198
199
200
201
  			return NULL;
  		}
  
  		liu = le16_to_cpu(cfi->lengthOfImpUse);
  		lfi = cfi->lengthFileIdent;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
202
  		if (fibh->sbh == fibh->ebh) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
203
  			nameptr = fi->fileIdent + liu;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
204
  		} else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
205
  			int poffset;	/* Unpaded ending offset */
cb00ea352   Cyrill Gorcunov   UDF: coding style...
206
207
208
  			poffset =
  			    fibh->soffset + sizeof(struct fileIdentDesc) + liu +
  			    lfi;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
209
210
  
  			if (poffset >= lfi)
cb00ea352   Cyrill Gorcunov   UDF: coding style...
211
212
213
214
  				nameptr =
  				    (uint8_t *) (fibh->ebh->b_data + poffset -
  						 lfi);
  			else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
215
  				nameptr = fname;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
216
217
218
219
  				memcpy(nameptr, fi->fileIdent + liu,
  				       lfi - poffset);
  				memcpy(nameptr + lfi - poffset,
  				       fibh->ebh->b_data, poffset);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
220
221
  			}
  		}
cb00ea352   Cyrill Gorcunov   UDF: coding style...
222
223
  		if ((cfi->fileCharacteristics & FID_FILE_CHAR_DELETED) != 0) {
  			if (!UDF_QUERY_FLAG(dir->i_sb, UDF_FLAG_UNDELETE))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
224
225
  				continue;
  		}
cb00ea352   Cyrill Gorcunov   UDF: coding style...
226
227
228
  
  		if ((cfi->fileCharacteristics & FID_FILE_CHAR_HIDDEN) != 0) {
  			if (!UDF_QUERY_FLAG(dir->i_sb, UDF_FLAG_UNHIDE))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
229
230
231
232
233
  				continue;
  		}
  
  		if (!lfi)
  			continue;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
234
235
236
237
  		if ((flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi))) {
  			if (udf_match
  			    (flen, fname, dentry->d_name.len,
  			     dentry->d_name.name)) {
3bf25cb40   Jan Kara   udf: use get_bh()
238
  				brelse(epos.bh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
239
240
241
242
243
  				return fi;
  			}
  		}
  	}
  	if (fibh->sbh != fibh->ebh)
3bf25cb40   Jan Kara   udf: use get_bh()
244
245
246
  		brelse(fibh->ebh);
  	brelse(fibh->sbh);
  	brelse(epos.bh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
  	return NULL;
  }
  
  /*
   * udf_lookup
   *
   * PURPOSE
   *	Look-up the inode for a given name.
   *
   * DESCRIPTION
   *	Required - lookup_dentry() will return -ENOTDIR if this routine is not
   *	available for a directory. The filesystem is useless if this routine is
   *	not available for at least the filesystem's root directory.
   *
   *	This routine is passed an incomplete dentry - it must be completed by
   *	calling d_add(dentry, inode). If the name does not exist, then the
   *	specified inode must be set to null. An error should only be returned
   *	when the lookup fails for a reason other than the name not existing.
   *	Note that the directory inode semaphore is held during the call.
   *
   *	Refer to lookup_dentry() in fs/namei.c
   *	lookup_dentry() -> lookup() -> real_lookup() -> .
   *
   * PRE-CONDITIONS
   *	dir			Pointer to inode of parent directory.
   *	dentry			Pointer to dentry to complete.
   *	nd			Pointer to lookup nameidata
   *
   * POST-CONDITIONS
   *	<return>		Zero on success.
   *
   * HISTORY
   *	July 1, 1997 - Andrew E. Mileski
   *	Written, tested, and released.
   */
cb00ea352   Cyrill Gorcunov   UDF: coding style...
282
283
  static struct dentry *udf_lookup(struct inode *dir, struct dentry *dentry,
  				 struct nameidata *nd)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
284
285
  {
  	struct inode *inode = NULL;
db9a369ec   Jayachandran C   [PATCH] UDF: Fix ...
286
  	struct fileIdentDesc cfi;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
287
  	struct udf_fileident_bh fibh;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
288
  	if (dentry->d_name.len > UDF_NAME_LEN - 2)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
289
290
291
292
293
  		return ERR_PTR(-ENAMETOOLONG);
  
  	lock_kernel();
  #ifdef UDF_RECOVERY
  	/* temporary shorthand for specifying files by inode number */
cb00ea352   Cyrill Gorcunov   UDF: coding style...
294
295
296
  	if (!strncmp(dentry->d_name.name, ".B=", 3)) {
  		kernel_lb_addr lb =
  		    { 0, simple_strtoul(dentry->d_name.name + 3, NULL, 0) };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
297
  		inode = udf_iget(dir->i_sb, lb);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
298
  		if (!inode) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
299
300
301
  			unlock_kernel();
  			return ERR_PTR(-EACCES);
  		}
cb00ea352   Cyrill Gorcunov   UDF: coding style...
302
303
  	} else
  #endif				/* UDF_RECOVERY */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
304

cb00ea352   Cyrill Gorcunov   UDF: coding style...
305
  	if (udf_find_entry(dir, dentry, &fibh, &cfi)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
306
  		if (fibh.sbh != fibh.ebh)
3bf25cb40   Jan Kara   udf: use get_bh()
307
308
  			brelse(fibh.ebh);
  		brelse(fibh.sbh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
309
310
  
  		inode = udf_iget(dir->i_sb, lelb_to_cpu(cfi.icb.extLocation));
cb00ea352   Cyrill Gorcunov   UDF: coding style...
311
  		if (!inode) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
312
313
314
315
316
317
318
319
  			unlock_kernel();
  			return ERR_PTR(-EACCES);
  		}
  	}
  	unlock_kernel();
  	d_add(dentry, inode);
  	return NULL;
  }
cb00ea352   Cyrill Gorcunov   UDF: coding style...
320
321
322
323
  static struct fileIdentDesc *udf_add_entry(struct inode *dir,
  					   struct dentry *dentry,
  					   struct udf_fileident_bh *fibh,
  					   struct fileIdentDesc *cfi, int *err)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
324
325
  {
  	struct super_block *sb;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
326
  	struct fileIdentDesc *fi = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
327
328
329
330
331
332
333
334
335
336
  	char name[UDF_NAME_LEN], fname[UDF_NAME_LEN];
  	int namelen;
  	loff_t f_pos;
  	int flen;
  	char *nameptr;
  	loff_t size = (udf_ext0_offset(dir) + dir->i_size) >> 2;
  	int nfidlen;
  	uint8_t lfi;
  	uint16_t liu;
  	int block;
ff116fc8d   Jan Kara   UDF: introduce st...
337
338
  	kernel_lb_addr eloc;
  	uint32_t elen;
60448b1d6   Jan Kara   udf: use sector_t...
339
  	sector_t offset;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
340
  	struct extent_position epos = { NULL, 0, {0, 0} };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
341
342
  
  	sb = dir->i_sb;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
343
344
  	if (dentry) {
  		if (!dentry->d_name.len) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
345
346
347
  			*err = -EINVAL;
  			return NULL;
  		}
cb00ea352   Cyrill Gorcunov   UDF: coding style...
348
349
350
351
  		if (!
  		    (namelen =
  		     udf_put_filename(sb, dentry->d_name.name, name,
  				      dentry->d_name.len))) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
352
353
354
  			*err = -ENAMETOOLONG;
  			return NULL;
  		}
cb00ea352   Cyrill Gorcunov   UDF: coding style...
355
  	} else
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
356
357
358
359
360
  		namelen = 0;
  
  	nfidlen = (sizeof(struct fileIdentDesc) + namelen + 3) & ~3;
  
  	f_pos = (udf_ext0_offset(dir) >> 2);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
361
362
  	fibh->soffset = fibh->eoffset =
  	    (f_pos & ((dir->i_sb->s_blocksize - 1) >> 2)) << 2;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
363
364
365
  	if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB)
  		fibh->sbh = fibh->ebh = NULL;
  	else if (inode_bmap(dir, f_pos >> (dir->i_sb->s_blocksize_bits - 2),
cb00ea352   Cyrill Gorcunov   UDF: coding style...
366
367
  			    &epos, &eloc, &elen,
  			    &offset) == (EXT_RECORDED_ALLOCATED >> 30)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
368
  		block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
369
  		if ((++offset << dir->i_sb->s_blocksize_bits) < elen) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
370
  			if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_SHORT)
ff116fc8d   Jan Kara   UDF: introduce st...
371
  				epos.offset -= sizeof(short_ad);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
372
  			else if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_LONG)
ff116fc8d   Jan Kara   UDF: introduce st...
373
  				epos.offset -= sizeof(long_ad);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
374
  		} else
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
375
  			offset = 0;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
376
  		if (!(fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block))) {
3bf25cb40   Jan Kara   udf: use get_bh()
377
  			brelse(epos.bh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
378
379
380
381
382
  			*err = -EIO;
  			return NULL;
  		}
  
  		block = UDF_I_LOCATION(dir).logicalBlockNum;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
383
  	} else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
384
385
386
387
388
  		block = udf_get_lb_pblock(dir->i_sb, UDF_I_LOCATION(dir), 0);
  		fibh->sbh = fibh->ebh = NULL;
  		fibh->soffset = fibh->eoffset = sb->s_blocksize;
  		goto add;
  	}
cb00ea352   Cyrill Gorcunov   UDF: coding style...
389
390
391
  	while ((f_pos < size)) {
  		fi = udf_fileident_read(dir, &f_pos, fibh, cfi, &epos, &eloc,
  					&elen, &offset);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
392

cb00ea352   Cyrill Gorcunov   UDF: coding style...
393
  		if (!fi) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
394
  			if (fibh->sbh != fibh->ebh)
3bf25cb40   Jan Kara   udf: use get_bh()
395
396
397
  				brelse(fibh->ebh);
  			brelse(fibh->sbh);
  			brelse(epos.bh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
398
399
400
401
402
403
404
405
406
  			*err = -EIO;
  			return NULL;
  		}
  
  		liu = le16_to_cpu(cfi->lengthOfImpUse);
  		lfi = cfi->lengthFileIdent;
  
  		if (fibh->sbh == fibh->ebh)
  			nameptr = fi->fileIdent + liu;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
407
  		else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
408
  			int poffset;	/* Unpaded ending offset */
cb00ea352   Cyrill Gorcunov   UDF: coding style...
409
410
411
  			poffset =
  			    fibh->soffset + sizeof(struct fileIdentDesc) + liu +
  			    lfi;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
412
413
  
  			if (poffset >= lfi)
cb00ea352   Cyrill Gorcunov   UDF: coding style...
414
415
416
  				nameptr =
  				    (char *)(fibh->ebh->b_data + poffset - lfi);
  			else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
417
  				nameptr = fname;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
418
419
420
421
  				memcpy(nameptr, fi->fileIdent + liu,
  				       lfi - poffset);
  				memcpy(nameptr + lfi - poffset,
  				       fibh->ebh->b_data, poffset);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
422
423
  			}
  		}
cb00ea352   Cyrill Gorcunov   UDF: coding style...
424
425
426
  		if ((cfi->fileCharacteristics & FID_FILE_CHAR_DELETED) != 0) {
  			if (((sizeof(struct fileIdentDesc) + liu + lfi +
  			      3) & ~3) == nfidlen) {
3bf25cb40   Jan Kara   udf: use get_bh()
427
  				brelse(epos.bh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
428
429
430
431
432
  				cfi->descTag.tagSerialNum = cpu_to_le16(1);
  				cfi->fileVersionNum = cpu_to_le16(1);
  				cfi->fileCharacteristics = 0;
  				cfi->lengthFileIdent = namelen;
  				cfi->lengthOfImpUse = cpu_to_le16(0);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
433
434
  				if (!udf_write_fi
  				    (dir, cfi, fi, fibh, NULL, name))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
435
  					return fi;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
436
  				else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
437
438
439
440
441
442
443
444
445
446
  					*err = -EIO;
  					return NULL;
  				}
  			}
  		}
  
  		if (!lfi || !dentry)
  			continue;
  
  		if ((flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi)) &&
cb00ea352   Cyrill Gorcunov   UDF: coding style...
447
448
  		    udf_match(flen, fname, dentry->d_name.len,
  			      dentry->d_name.name)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
449
  			if (fibh->sbh != fibh->ebh)
3bf25cb40   Jan Kara   udf: use get_bh()
450
451
452
  				brelse(fibh->ebh);
  			brelse(fibh->sbh);
  			brelse(epos.bh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
453
454
455
456
  			*err = -EEXIST;
  			return NULL;
  		}
  	}
cb00ea352   Cyrill Gorcunov   UDF: coding style...
457
        add:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
458
459
460
  	f_pos += nfidlen;
  
  	if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB &&
cb00ea352   Cyrill Gorcunov   UDF: coding style...
461
  	    sb->s_blocksize - fibh->eoffset < nfidlen) {
3bf25cb40   Jan Kara   udf: use get_bh()
462
  		brelse(epos.bh);
ff116fc8d   Jan Kara   UDF: introduce st...
463
  		epos.bh = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
464
465
466
467
  		fibh->soffset -= udf_ext0_offset(dir);
  		fibh->eoffset -= udf_ext0_offset(dir);
  		f_pos -= (udf_ext0_offset(dir) >> 2);
  		if (fibh->sbh != fibh->ebh)
3bf25cb40   Jan Kara   udf: use get_bh()
468
469
  			brelse(fibh->ebh);
  		brelse(fibh->sbh);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
470
471
472
  		if (!
  		    (fibh->sbh = fibh->ebh =
  		     udf_expand_dir_adinicb(dir, &block, err)))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
473
  			return NULL;
ff116fc8d   Jan Kara   UDF: introduce st...
474
  		epos.block = UDF_I_LOCATION(dir);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
475
  		eloc.logicalBlockNum = block;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
476
477
  		eloc.partitionReferenceNum =
  		    UDF_I_LOCATION(dir).partitionReferenceNum;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
478
  		elen = dir->i_sb->s_blocksize;
ff116fc8d   Jan Kara   UDF: introduce st...
479
  		epos.offset = udf_file_entry_alloc_offset(dir);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
480
  		if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_SHORT)
ff116fc8d   Jan Kara   UDF: introduce st...
481
  			epos.offset += sizeof(short_ad);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
482
  		else if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_LONG)
ff116fc8d   Jan Kara   UDF: introduce st...
483
  			epos.offset += sizeof(long_ad);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
484
  	}
cb00ea352   Cyrill Gorcunov   UDF: coding style...
485
  	if (sb->s_blocksize - fibh->eoffset >= nfidlen) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
486
487
  		fibh->soffset = fibh->eoffset;
  		fibh->eoffset += nfidlen;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
488
  		if (fibh->sbh != fibh->ebh) {
3bf25cb40   Jan Kara   udf: use get_bh()
489
  			brelse(fibh->sbh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
490
491
  			fibh->sbh = fibh->ebh;
  		}
cb00ea352   Cyrill Gorcunov   UDF: coding style...
492
  		if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
493
  			block = UDF_I_LOCATION(dir).logicalBlockNum;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
494
495
496
497
498
  			fi = (struct fileIdentDesc *)(UDF_I_DATA(dir) +
  						      fibh->soffset -
  						      udf_ext0_offset(dir) +
  						      UDF_I_LENEATTR(dir));
  		} else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
499
  			block = eloc.logicalBlockNum + ((elen - 1) >>
cb00ea352   Cyrill Gorcunov   UDF: coding style...
500
501
502
503
  							dir->i_sb->
  							s_blocksize_bits);
  			fi = (struct fileIdentDesc *)(fibh->sbh->b_data +
  						      fibh->soffset);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
504
  		}
cb00ea352   Cyrill Gorcunov   UDF: coding style...
505
  	} else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
506
507
  		fibh->soffset = fibh->eoffset - sb->s_blocksize;
  		fibh->eoffset += nfidlen - sb->s_blocksize;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
508
  		if (fibh->sbh != fibh->ebh) {
3bf25cb40   Jan Kara   udf: use get_bh()
509
  			brelse(fibh->sbh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
510
511
512
513
  			fibh->sbh = fibh->ebh;
  		}
  
  		block = eloc.logicalBlockNum + ((elen - 1) >>
cb00ea352   Cyrill Gorcunov   UDF: coding style...
514
  						dir->i_sb->s_blocksize_bits);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
515

cb00ea352   Cyrill Gorcunov   UDF: coding style...
516
517
518
519
  		if (!
  		    (fibh->ebh =
  		     udf_bread(dir, f_pos >> (dir->i_sb->s_blocksize_bits - 2),
  			       1, err))) {
3bf25cb40   Jan Kara   udf: use get_bh()
520
521
  			brelse(epos.bh);
  			brelse(fibh->sbh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
522
523
  			return NULL;
  		}
cb00ea352   Cyrill Gorcunov   UDF: coding style...
524
  		if (!(fibh->soffset)) {
ff116fc8d   Jan Kara   UDF: introduce st...
525
  			if (udf_next_aext(dir, &epos, &eloc, &elen, 1) ==
cb00ea352   Cyrill Gorcunov   UDF: coding style...
526
  			    (EXT_RECORDED_ALLOCATED >> 30)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
527
  				block = eloc.logicalBlockNum + ((elen - 1) >>
cb00ea352   Cyrill Gorcunov   UDF: coding style...
528
529
530
531
  								dir->i_sb->
  								s_blocksize_bits);
  			} else
  				block++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
532

3bf25cb40   Jan Kara   udf: use get_bh()
533
  			brelse(fibh->sbh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
534
535
  			fibh->sbh = fibh->ebh;
  			fi = (struct fileIdentDesc *)(fibh->sbh->b_data);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
536
  		} else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
537
  			fi = (struct fileIdentDesc *)
cb00ea352   Cyrill Gorcunov   UDF: coding style...
538
539
  			    (fibh->sbh->b_data + sb->s_blocksize +
  			     fibh->soffset);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
540
541
542
543
544
  		}
  	}
  
  	memset(cfi, 0, sizeof(struct fileIdentDesc));
  	if (UDF_SB_UDFREV(sb) >= 0x0200)
cb00ea352   Cyrill Gorcunov   UDF: coding style...
545
546
  		udf_new_tag((char *)cfi, TAG_IDENT_FID, 3, 1, block,
  			    sizeof(tag));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
547
  	else
cb00ea352   Cyrill Gorcunov   UDF: coding style...
548
549
  		udf_new_tag((char *)cfi, TAG_IDENT_FID, 2, 1, block,
  			    sizeof(tag));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
550
551
552
  	cfi->fileVersionNum = cpu_to_le16(1);
  	cfi->lengthFileIdent = namelen;
  	cfi->lengthOfImpUse = cpu_to_le16(0);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
553
  	if (!udf_write_fi(dir, cfi, fi, fibh, NULL, name)) {
3bf25cb40   Jan Kara   udf: use get_bh()
554
  		brelse(epos.bh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
555
556
557
558
559
  		dir->i_size += nfidlen;
  		if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB)
  			UDF_I_LENALLOC(dir) += nfidlen;
  		mark_inode_dirty(dir);
  		return fi;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
560
  	} else {
3bf25cb40   Jan Kara   udf: use get_bh()
561
  		brelse(epos.bh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
562
  		if (fibh->sbh != fibh->ebh)
3bf25cb40   Jan Kara   udf: use get_bh()
563
564
  			brelse(fibh->ebh);
  		brelse(fibh->sbh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
565
566
567
568
569
570
  		*err = -EIO;
  		return NULL;
  	}
  }
  
  static int udf_delete_entry(struct inode *inode, struct fileIdentDesc *fi,
cb00ea352   Cyrill Gorcunov   UDF: coding style...
571
572
  			    struct udf_fileident_bh *fibh,
  			    struct fileIdentDesc *cfi)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
573
574
575
576
577
578
  {
  	cfi->fileCharacteristics |= FID_FILE_CHAR_DELETED;
  	if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT))
  		memset(&(cfi->icb), 0x00, sizeof(long_ad));
  	return udf_write_fi(inode, cfi, fi, fibh, NULL, NULL);
  }
cb00ea352   Cyrill Gorcunov   UDF: coding style...
579
580
  static int udf_create(struct inode *dir, struct dentry *dentry, int mode,
  		      struct nameidata *nd)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
581
582
583
584
585
586
587
588
  {
  	struct udf_fileident_bh fibh;
  	struct inode *inode;
  	struct fileIdentDesc cfi, *fi;
  	int err;
  
  	lock_kernel();
  	inode = udf_new_inode(dir, mode, &err);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
589
  	if (!inode) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
590
591
592
593
594
595
596
597
598
599
600
601
  		unlock_kernel();
  		return err;
  	}
  
  	if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_IN_ICB)
  		inode->i_data.a_ops = &udf_adinicb_aops;
  	else
  		inode->i_data.a_ops = &udf_aops;
  	inode->i_op = &udf_file_inode_operations;
  	inode->i_fop = &udf_file_operations;
  	inode->i_mode = mode;
  	mark_inode_dirty(inode);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
602
603
  	if (!(fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err))) {
  		inode->i_nlink--;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
604
605
606
607
608
609
610
  		mark_inode_dirty(inode);
  		iput(inode);
  		unlock_kernel();
  		return err;
  	}
  	cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
  	cfi.icb.extLocation = cpu_to_lelb(UDF_I_LOCATION(inode));
cb00ea352   Cyrill Gorcunov   UDF: coding style...
611
612
  	*(__le32 *) ((struct allocDescImpUse *)cfi.icb.impUse)->impUse =
  	    cpu_to_le32(UDF_I_UNIQUE(inode) & 0x00000000FFFFFFFFUL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
613
  	udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
614
  	if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
615
616
617
  		mark_inode_dirty(dir);
  	}
  	if (fibh.sbh != fibh.ebh)
3bf25cb40   Jan Kara   udf: use get_bh()
618
619
  		brelse(fibh.ebh);
  	brelse(fibh.sbh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
620
621
622
623
  	unlock_kernel();
  	d_instantiate(dentry, inode);
  	return 0;
  }
cb00ea352   Cyrill Gorcunov   UDF: coding style...
624
625
  static int udf_mknod(struct inode *dir, struct dentry *dentry, int mode,
  		     dev_t rdev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
626
  {
cb00ea352   Cyrill Gorcunov   UDF: coding style...
627
  	struct inode *inode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
  	struct udf_fileident_bh fibh;
  	struct fileIdentDesc cfi, *fi;
  	int err;
  
  	if (!old_valid_dev(rdev))
  		return -EINVAL;
  
  	lock_kernel();
  	err = -EIO;
  	inode = udf_new_inode(dir, mode, &err);
  	if (!inode)
  		goto out;
  
  	inode->i_uid = current->fsuid;
  	init_special_inode(inode, mode, rdev);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
643
644
  	if (!(fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err))) {
  		inode->i_nlink--;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
645
646
647
648
649
650
651
  		mark_inode_dirty(inode);
  		iput(inode);
  		unlock_kernel();
  		return err;
  	}
  	cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
  	cfi.icb.extLocation = cpu_to_lelb(UDF_I_LOCATION(inode));
cb00ea352   Cyrill Gorcunov   UDF: coding style...
652
653
  	*(__le32 *) ((struct allocDescImpUse *)cfi.icb.impUse)->impUse =
  	    cpu_to_le32(UDF_I_UNIQUE(inode) & 0x00000000FFFFFFFFUL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
654
  	udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
655
  	if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
656
657
658
659
660
  		mark_inode_dirty(dir);
  	}
  	mark_inode_dirty(inode);
  
  	if (fibh.sbh != fibh.ebh)
3bf25cb40   Jan Kara   udf: use get_bh()
661
662
  		brelse(fibh.ebh);
  	brelse(fibh.sbh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
663
664
  	d_instantiate(dentry, inode);
  	err = 0;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
665
        out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
666
667
668
  	unlock_kernel();
  	return err;
  }
cb00ea352   Cyrill Gorcunov   UDF: coding style...
669
  static int udf_mkdir(struct inode *dir, struct dentry *dentry, int mode)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
670
  {
cb00ea352   Cyrill Gorcunov   UDF: coding style...
671
  	struct inode *inode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
672
673
674
675
676
677
  	struct udf_fileident_bh fibh;
  	struct fileIdentDesc cfi, *fi;
  	int err;
  
  	lock_kernel();
  	err = -EMLINK;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
678
  	if (dir->i_nlink >= (256 << sizeof(dir->i_nlink)) - 1)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
679
680
681
682
683
684
685
686
687
  		goto out;
  
  	err = -EIO;
  	inode = udf_new_inode(dir, S_IFDIR, &err);
  	if (!inode)
  		goto out;
  
  	inode->i_op = &udf_dir_inode_operations;
  	inode->i_fop = &udf_dir_operations;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
688
  	if (!(fi = udf_add_entry(inode, NULL, &fibh, &cfi, &err))) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
689
690
691
692
693
694
695
696
  		inode->i_nlink--;
  		mark_inode_dirty(inode);
  		iput(inode);
  		goto out;
  	}
  	inode->i_nlink = 2;
  	cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
  	cfi.icb.extLocation = cpu_to_lelb(UDF_I_LOCATION(dir));
cb00ea352   Cyrill Gorcunov   UDF: coding style...
697
698
699
700
  	*(__le32 *) ((struct allocDescImpUse *)cfi.icb.impUse)->impUse =
  	    cpu_to_le32(UDF_I_UNIQUE(dir) & 0x00000000FFFFFFFFUL);
  	cfi.fileCharacteristics =
  	    FID_FILE_CHAR_DIRECTORY | FID_FILE_CHAR_PARENT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
701
  	udf_write_fi(inode, &cfi, fi, &fibh, NULL, NULL);
3bf25cb40   Jan Kara   udf: use get_bh()
702
  	brelse(fibh.sbh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
703
704
705
706
  	inode->i_mode = S_IFDIR | mode;
  	if (dir->i_mode & S_ISGID)
  		inode->i_mode |= S_ISGID;
  	mark_inode_dirty(inode);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
707
  	if (!(fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err))) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
708
709
710
711
712
713
714
  		inode->i_nlink = 0;
  		mark_inode_dirty(inode);
  		iput(inode);
  		goto out;
  	}
  	cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
  	cfi.icb.extLocation = cpu_to_lelb(UDF_I_LOCATION(inode));
cb00ea352   Cyrill Gorcunov   UDF: coding style...
715
716
  	*(__le32 *) ((struct allocDescImpUse *)cfi.icb.impUse)->impUse =
  	    cpu_to_le32(UDF_I_UNIQUE(inode) & 0x00000000FFFFFFFFUL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
717
718
  	cfi.fileCharacteristics |= FID_FILE_CHAR_DIRECTORY;
  	udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL);
d8c76e6f4   Dave Hansen   [PATCH] r/o bind ...
719
  	inc_nlink(dir);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
720
721
722
  	mark_inode_dirty(dir);
  	d_instantiate(dentry, inode);
  	if (fibh.sbh != fibh.ebh)
3bf25cb40   Jan Kara   udf: use get_bh()
723
724
  		brelse(fibh.ebh);
  	brelse(fibh.sbh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
725
  	err = 0;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
726
        out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
727
728
729
730
731
732
733
734
735
736
737
  	unlock_kernel();
  	return err;
  }
  
  static int empty_dir(struct inode *dir)
  {
  	struct fileIdentDesc *fi, cfi;
  	struct udf_fileident_bh fibh;
  	loff_t f_pos;
  	loff_t size = (udf_ext0_offset(dir) + dir->i_size) >> 2;
  	int block;
ff116fc8d   Jan Kara   UDF: introduce st...
738
739
  	kernel_lb_addr eloc;
  	uint32_t elen;
60448b1d6   Jan Kara   udf: use sector_t...
740
  	sector_t offset;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
741
  	struct extent_position epos = { NULL, 0, {0, 0} };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
742
743
  
  	f_pos = (udf_ext0_offset(dir) >> 2);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
744
745
  	fibh.soffset = fibh.eoffset =
  	    (f_pos & ((dir->i_sb->s_blocksize - 1) >> 2)) << 2;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
746
747
748
749
  
  	if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB)
  		fibh.sbh = fibh.ebh = NULL;
  	else if (inode_bmap(dir, f_pos >> (dir->i_sb->s_blocksize_bits - 2),
cb00ea352   Cyrill Gorcunov   UDF: coding style...
750
751
  			    &epos, &eloc, &elen,
  			    &offset) == (EXT_RECORDED_ALLOCATED >> 30)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
752
  		block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
753
  		if ((++offset << dir->i_sb->s_blocksize_bits) < elen) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
754
  			if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_SHORT)
ff116fc8d   Jan Kara   UDF: introduce st...
755
  				epos.offset -= sizeof(short_ad);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
756
  			else if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_LONG)
ff116fc8d   Jan Kara   UDF: introduce st...
757
  				epos.offset -= sizeof(long_ad);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
758
  		} else
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
759
  			offset = 0;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
760
  		if (!(fibh.sbh = fibh.ebh = udf_tread(dir->i_sb, block))) {
3bf25cb40   Jan Kara   udf: use get_bh()
761
  			brelse(epos.bh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
762
763
  			return 0;
  		}
cb00ea352   Cyrill Gorcunov   UDF: coding style...
764
  	} else {
3bf25cb40   Jan Kara   udf: use get_bh()
765
  		brelse(epos.bh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
766
767
  		return 0;
  	}
cb00ea352   Cyrill Gorcunov   UDF: coding style...
768
769
770
  	while ((f_pos < size)) {
  		fi = udf_fileident_read(dir, &f_pos, &fibh, &cfi, &epos, &eloc,
  					&elen, &offset);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
771

cb00ea352   Cyrill Gorcunov   UDF: coding style...
772
  		if (!fi) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
773
  			if (fibh.sbh != fibh.ebh)
3bf25cb40   Jan Kara   udf: use get_bh()
774
775
776
  				brelse(fibh.ebh);
  			brelse(fibh.sbh);
  			brelse(epos.bh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
777
778
  			return 0;
  		}
cb00ea352   Cyrill Gorcunov   UDF: coding style...
779
780
  		if (cfi.lengthFileIdent
  		    && (cfi.fileCharacteristics & FID_FILE_CHAR_DELETED) == 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
781
  			if (fibh.sbh != fibh.ebh)
3bf25cb40   Jan Kara   udf: use get_bh()
782
783
784
  				brelse(fibh.ebh);
  			brelse(fibh.sbh);
  			brelse(epos.bh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
785
786
787
788
  			return 0;
  		}
  	}
  	if (fibh.sbh != fibh.ebh)
3bf25cb40   Jan Kara   udf: use get_bh()
789
790
791
  		brelse(fibh.ebh);
  	brelse(fibh.sbh);
  	brelse(epos.bh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
792
793
  	return 1;
  }
cb00ea352   Cyrill Gorcunov   UDF: coding style...
794
  static int udf_rmdir(struct inode *dir, struct dentry *dentry)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
795
796
  {
  	int retval;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
797
  	struct inode *inode = dentry->d_inode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
  	struct udf_fileident_bh fibh;
  	struct fileIdentDesc *fi, cfi;
  	kernel_lb_addr tloc;
  
  	retval = -ENOENT;
  	lock_kernel();
  	fi = udf_find_entry(dir, dentry, &fibh, &cfi);
  	if (!fi)
  		goto out;
  
  	retval = -EIO;
  	tloc = lelb_to_cpu(cfi.icb.extLocation);
  	if (udf_get_lb_pblock(dir->i_sb, tloc, 0) != inode->i_ino)
  		goto end_rmdir;
  	retval = -ENOTEMPTY;
  	if (!empty_dir(inode))
  		goto end_rmdir;
  	retval = udf_delete_entry(dir, fi, &fibh, &cfi);
  	if (retval)
  		goto end_rmdir;
  	if (inode->i_nlink != 2)
  		udf_warning(inode->i_sb, "udf_rmdir",
cb00ea352   Cyrill Gorcunov   UDF: coding style...
820
821
  			    "empty directory has nlink != 2 (%d)",
  			    inode->i_nlink);
ce71ec368   Dave Hansen   [PATCH] r/o bind ...
822
  	clear_nlink(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
823
  	inode->i_size = 0;
c007c06e3   Stephen Mollett   udf: decrement co...
824
  	inode_dec_link_count(dir);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
825
826
  	inode->i_ctime = dir->i_ctime = dir->i_mtime =
  	    current_fs_time(dir->i_sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
827
  	mark_inode_dirty(dir);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
828
        end_rmdir:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
829
  	if (fibh.sbh != fibh.ebh)
3bf25cb40   Jan Kara   udf: use get_bh()
830
831
  		brelse(fibh.ebh);
  	brelse(fibh.sbh);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
832
        out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
833
834
835
  	unlock_kernel();
  	return retval;
  }
cb00ea352   Cyrill Gorcunov   UDF: coding style...
836
  static int udf_unlink(struct inode *dir, struct dentry *dentry)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
837
838
  {
  	int retval;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
839
  	struct inode *inode = dentry->d_inode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
  	struct udf_fileident_bh fibh;
  	struct fileIdentDesc *fi;
  	struct fileIdentDesc cfi;
  	kernel_lb_addr tloc;
  
  	retval = -ENOENT;
  	lock_kernel();
  	fi = udf_find_entry(dir, dentry, &fibh, &cfi);
  	if (!fi)
  		goto out;
  
  	retval = -EIO;
  	tloc = lelb_to_cpu(cfi.icb.extLocation);
  	if (udf_get_lb_pblock(dir->i_sb, tloc, 0) != inode->i_ino)
  		goto end_unlink;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
855
  	if (!inode->i_nlink) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
856
857
  		udf_debug("Deleting nonexistent file (%lu), %d
  ",
cb00ea352   Cyrill Gorcunov   UDF: coding style...
858
  			  inode->i_ino, inode->i_nlink);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
859
860
861
862
863
864
865
  		inode->i_nlink = 1;
  	}
  	retval = udf_delete_entry(dir, fi, &fibh, &cfi);
  	if (retval)
  		goto end_unlink;
  	dir->i_ctime = dir->i_mtime = current_fs_time(dir->i_sb);
  	mark_inode_dirty(dir);
9a53c3a78   Dave Hansen   [PATCH] r/o bind ...
866
  	inode_dec_link_count(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
867
868
  	inode->i_ctime = dir->i_ctime;
  	retval = 0;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
869
        end_unlink:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
870
  	if (fibh.sbh != fibh.ebh)
3bf25cb40   Jan Kara   udf: use get_bh()
871
872
  		brelse(fibh.ebh);
  	brelse(fibh.sbh);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
873
        out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
874
875
876
  	unlock_kernel();
  	return retval;
  }
cb00ea352   Cyrill Gorcunov   UDF: coding style...
877
878
  static int udf_symlink(struct inode *dir, struct dentry *dentry,
  		       const char *symname)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
879
  {
cb00ea352   Cyrill Gorcunov   UDF: coding style...
880
  	struct inode *inode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
881
882
883
  	struct pathComponent *pc;
  	char *compstart;
  	struct udf_fileident_bh fibh;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
884
  	struct extent_position epos = { NULL, 0, {0, 0} };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
  	int eoffset, elen = 0;
  	struct fileIdentDesc *fi;
  	struct fileIdentDesc cfi;
  	char *ea;
  	int err;
  	int block;
  	char name[UDF_NAME_LEN];
  	int namelen;
  
  	lock_kernel();
  	if (!(inode = udf_new_inode(dir, S_IFLNK, &err)))
  		goto out;
  
  	inode->i_mode = S_IFLNK | S_IRWXUGO;
  	inode->i_data.a_ops = &udf_symlink_aops;
  	inode->i_op = &page_symlink_inode_operations;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
901
  	if (UDF_I_ALLOCTYPE(inode) != ICBTAG_FLAG_AD_IN_ICB) {
ff116fc8d   Jan Kara   UDF: introduce st...
902
903
  		kernel_lb_addr eloc;
  		uint32_t elen;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
904
905
  
  		block = udf_new_block(inode->i_sb, inode,
cb00ea352   Cyrill Gorcunov   UDF: coding style...
906
907
908
909
  				      UDF_I_LOCATION(inode).
  				      partitionReferenceNum,
  				      UDF_I_LOCATION(inode).logicalBlockNum,
  				      &err);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
910
911
  		if (!block)
  			goto out_no_entry;
ff116fc8d   Jan Kara   UDF: introduce st...
912
913
914
  		epos.block = UDF_I_LOCATION(inode);
  		epos.offset = udf_file_entry_alloc_offset(inode);
  		epos.bh = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
915
  		eloc.logicalBlockNum = block;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
916
917
  		eloc.partitionReferenceNum =
  		    UDF_I_LOCATION(inode).partitionReferenceNum;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
918
919
  		elen = inode->i_sb->s_blocksize;
  		UDF_I_LENEXTENTS(inode) = elen;
ff116fc8d   Jan Kara   UDF: introduce st...
920
  		udf_add_aext(inode, &epos, eloc, elen, 0);
3bf25cb40   Jan Kara   udf: use get_bh()
921
  		brelse(epos.bh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
922
923
  
  		block = udf_get_pblock(inode->i_sb, block,
cb00ea352   Cyrill Gorcunov   UDF: coding style...
924
925
  				       UDF_I_LOCATION(inode).
  				       partitionReferenceNum, 0);
ff116fc8d   Jan Kara   UDF: introduce st...
926
927
928
929
930
931
932
  		epos.bh = udf_tread(inode->i_sb, block);
  		lock_buffer(epos.bh);
  		memset(epos.bh->b_data, 0x00, inode->i_sb->s_blocksize);
  		set_buffer_uptodate(epos.bh);
  		unlock_buffer(epos.bh);
  		mark_buffer_dirty_inode(epos.bh, inode);
  		ea = epos.bh->b_data + udf_ext0_offset(inode);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
933
  	} else
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
934
935
936
937
  		ea = UDF_I_DATA(inode) + UDF_I_LENEATTR(inode);
  
  	eoffset = inode->i_sb->s_blocksize - udf_ext0_offset(inode);
  	pc = (struct pathComponent *)ea;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
938
939
  	if (*symname == '/') {
  		do {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
940
941
942
943
944
945
946
947
948
949
950
  			symname++;
  		} while (*symname == '/');
  
  		pc->componentType = 1;
  		pc->lengthComponentIdent = 0;
  		pc->componentFileVersionNum = 0;
  		pc += sizeof(struct pathComponent);
  		elen += sizeof(struct pathComponent);
  	}
  
  	err = -ENAMETOOLONG;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
951
  	while (*symname) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
952
953
954
955
956
957
  		if (elen + sizeof(struct pathComponent) > eoffset)
  			goto out_no_entry;
  
  		pc = (struct pathComponent *)(ea + elen);
  
  		compstart = (char *)symname;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
958
  		do {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
959
960
961
962
963
964
  			symname++;
  		} while (*symname && *symname != '/');
  
  		pc->componentType = 5;
  		pc->lengthComponentIdent = 0;
  		pc->componentFileVersionNum = 0;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
965
966
  		if (compstart[0] == '.') {
  			if ((symname - compstart) == 1)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
967
  				pc->componentType = 4;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
968
969
  			else if ((symname - compstart) == 2
  				 && compstart[1] == '.')
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
970
971
  				pc->componentType = 3;
  		}
cb00ea352   Cyrill Gorcunov   UDF: coding style...
972
973
974
975
976
  		if (pc->componentType == 5) {
  			if (!
  			    (namelen =
  			     udf_put_filename(inode->i_sb, compstart, name,
  					      symname - compstart)))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
977
  				goto out_no_entry;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
978
979
  			if (elen + sizeof(struct pathComponent) + namelen >
  			    eoffset)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
980
981
982
983
984
985
986
987
  				goto out_no_entry;
  			else
  				pc->lengthComponentIdent = namelen;
  
  			memcpy(pc->componentIdent, name, namelen);
  		}
  
  		elen += sizeof(struct pathComponent) + pc->lengthComponentIdent;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
988
989
  		if (*symname) {
  			do {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
990
991
992
993
  				symname++;
  			} while (*symname == '/');
  		}
  	}
3bf25cb40   Jan Kara   udf: use get_bh()
994
  	brelse(epos.bh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
995
996
997
998
999
1000
1001
1002
1003
  	inode->i_size = elen;
  	if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_IN_ICB)
  		UDF_I_LENALLOC(inode) = inode->i_size;
  	mark_inode_dirty(inode);
  
  	if (!(fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err)))
  		goto out_no_entry;
  	cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
  	cfi.icb.extLocation = cpu_to_lelb(UDF_I_LOCATION(inode));
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1004
  	if (UDF_SB_LVIDBH(inode->i_sb)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1005
1006
  		struct logicalVolHeaderDesc *lvhd;
  		uint64_t uniqueID;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1007
1008
1009
  		lvhd =
  		    (struct logicalVolHeaderDesc *)(UDF_SB_LVID(inode->i_sb)->
  						    logicalVolContentsUse);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1010
  		uniqueID = le64_to_cpu(lvhd->uniqueID);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1011
1012
  		*(__le32 *) ((struct allocDescImpUse *)cfi.icb.impUse)->impUse =
  		    cpu_to_le32(uniqueID & 0x00000000FFFFFFFFUL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1013
1014
1015
1016
1017
1018
  		if (!(++uniqueID & 0x00000000FFFFFFFFUL))
  			uniqueID += 16;
  		lvhd->uniqueID = cpu_to_le64(uniqueID);
  		mark_buffer_dirty(UDF_SB_LVIDBH(inode->i_sb));
  	}
  	udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1019
  	if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1020
1021
1022
  		mark_inode_dirty(dir);
  	}
  	if (fibh.sbh != fibh.ebh)
3bf25cb40   Jan Kara   udf: use get_bh()
1023
1024
  		brelse(fibh.ebh);
  	brelse(fibh.sbh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1025
1026
  	d_instantiate(dentry, inode);
  	err = 0;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1027
        out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1028
1029
  	unlock_kernel();
  	return err;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1030
        out_no_entry:
9a53c3a78   Dave Hansen   [PATCH] r/o bind ...
1031
  	inode_dec_link_count(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1032
1033
1034
  	iput(inode);
  	goto out;
  }
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1035
1036
  static int udf_link(struct dentry *old_dentry, struct inode *dir,
  		    struct dentry *dentry)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1037
1038
1039
1040
1041
1042
1043
  {
  	struct inode *inode = old_dentry->d_inode;
  	struct udf_fileident_bh fibh;
  	struct fileIdentDesc cfi, *fi;
  	int err;
  
  	lock_kernel();
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1044
  	if (inode->i_nlink >= (256 << sizeof(inode->i_nlink)) - 1) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1045
1046
1047
  		unlock_kernel();
  		return -EMLINK;
  	}
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1048
  	if (!(fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err))) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1049
1050
1051
1052
1053
  		unlock_kernel();
  		return err;
  	}
  	cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
  	cfi.icb.extLocation = cpu_to_lelb(UDF_I_LOCATION(inode));
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1054
  	if (UDF_SB_LVIDBH(inode->i_sb)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1055
1056
  		struct logicalVolHeaderDesc *lvhd;
  		uint64_t uniqueID;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1057
1058
1059
  		lvhd =
  		    (struct logicalVolHeaderDesc *)(UDF_SB_LVID(inode->i_sb)->
  						    logicalVolContentsUse);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1060
  		uniqueID = le64_to_cpu(lvhd->uniqueID);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1061
1062
  		*(__le32 *) ((struct allocDescImpUse *)cfi.icb.impUse)->impUse =
  		    cpu_to_le32(uniqueID & 0x00000000FFFFFFFFUL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1063
1064
1065
1066
1067
1068
  		if (!(++uniqueID & 0x00000000FFFFFFFFUL))
  			uniqueID += 16;
  		lvhd->uniqueID = cpu_to_le64(uniqueID);
  		mark_buffer_dirty(UDF_SB_LVIDBH(inode->i_sb));
  	}
  	udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1069
  	if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1070
1071
1072
  		mark_inode_dirty(dir);
  	}
  	if (fibh.sbh != fibh.ebh)
3bf25cb40   Jan Kara   udf: use get_bh()
1073
1074
  		brelse(fibh.ebh);
  	brelse(fibh.sbh);
d8c76e6f4   Dave Hansen   [PATCH] r/o bind ...
1075
  	inc_nlink(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
  	inode->i_ctime = current_fs_time(inode->i_sb);
  	mark_inode_dirty(inode);
  	atomic_inc(&inode->i_count);
  	d_instantiate(dentry, inode);
  	unlock_kernel();
  	return 0;
  }
  
  /* Anybody can rename anything with this: the permission checks are left to the
   * higher-level routines.
   */
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1087
1088
  static int udf_rename(struct inode *old_dir, struct dentry *old_dentry,
  		      struct inode *new_dir, struct dentry *new_dentry)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1089
  {
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1090
1091
  	struct inode *old_inode = old_dentry->d_inode;
  	struct inode *new_inode = new_dentry->d_inode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1092
  	struct udf_fileident_bh ofibh, nfibh;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1093
1094
  	struct fileIdentDesc *ofi = NULL, *nfi = NULL, *dir_fi =
  	    NULL, ocfi, ncfi;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1095
1096
1097
1098
1099
  	struct buffer_head *dir_bh = NULL;
  	int retval = -ENOENT;
  	kernel_lb_addr tloc;
  
  	lock_kernel();
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1100
  	if ((ofi = udf_find_entry(old_dir, old_dentry, &ofibh, &ocfi))) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1101
  		if (ofibh.sbh != ofibh.ebh)
3bf25cb40   Jan Kara   udf: use get_bh()
1102
1103
  			brelse(ofibh.ebh);
  		brelse(ofibh.sbh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1104
1105
1106
  	}
  	tloc = lelb_to_cpu(ocfi.icb.extLocation);
  	if (!ofi || udf_get_lb_pblock(old_dir->i_sb, tloc, 0)
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1107
  	    != old_inode->i_ino)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1108
1109
1110
  		goto end_rename;
  
  	nfi = udf_find_entry(new_dir, new_dentry, &nfibh, &ncfi);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1111
1112
  	if (nfi) {
  		if (!new_inode) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1113
  			if (nfibh.sbh != nfibh.ebh)
3bf25cb40   Jan Kara   udf: use get_bh()
1114
1115
  				brelse(nfibh.ebh);
  			brelse(nfibh.sbh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1116
1117
1118
  			nfi = NULL;
  		}
  	}
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1119
  	if (S_ISDIR(old_inode->i_mode)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1120
  		uint32_t offset = udf_ext0_offset(old_inode);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1121
  		if (new_inode) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1122
1123
1124
1125
1126
  			retval = -ENOTEMPTY;
  			if (!empty_dir(new_inode))
  				goto end_rename;
  		}
  		retval = -EIO;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1127
  		if (UDF_I_ALLOCTYPE(old_inode) == ICBTAG_FLAG_AD_IN_ICB) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1128
  			dir_fi = udf_get_fileident(UDF_I_DATA(old_inode) -
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1129
1130
1131
1132
1133
1134
1135
  						   (UDF_I_EFE(old_inode) ?
  						    sizeof(struct
  							   extendedFileEntry) :
  						    sizeof(struct fileEntry)),
  						   old_inode->i_sb->s_blocksize,
  						   &offset);
  		} else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1136
1137
1138
  			dir_bh = udf_bread(old_inode, 0, 0, &retval);
  			if (!dir_bh)
  				goto end_rename;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1139
1140
1141
1142
  			dir_fi =
  			    udf_get_fileident(dir_bh->b_data,
  					      old_inode->i_sb->s_blocksize,
  					      &offset);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1143
1144
1145
1146
1147
  		}
  		if (!dir_fi)
  			goto end_rename;
  		tloc = lelb_to_cpu(dir_fi->icb.extLocation);
  		if (udf_get_lb_pblock(old_inode->i_sb, tloc, 0)
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1148
  		    != old_dir->i_ino)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1149
1150
1151
  			goto end_rename;
  
  		retval = -EMLINK;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1152
1153
1154
  		if (!new_inode
  		    && new_dir->i_nlink >=
  		    (256 << sizeof(new_dir->i_nlink)) - 1)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1155
1156
  			goto end_rename;
  	}
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1157
1158
1159
  	if (!nfi) {
  		nfi =
  		    udf_add_entry(new_dir, new_dentry, &nfibh, &ncfi, &retval);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
  		if (!nfi)
  			goto end_rename;
  	}
  
  	/*
  	 * Like most other Unix systems, set the ctime for inodes on a
  	 * rename.
  	 */
  	old_inode->i_ctime = current_fs_time(old_inode->i_sb);
  	mark_inode_dirty(old_inode);
  
  	/*
  	 * ok, that's it
  	 */
  	ncfi.fileVersionNum = ocfi.fileVersionNum;
  	ncfi.fileCharacteristics = ocfi.fileCharacteristics;
  	memcpy(&(ncfi.icb), &(ocfi.icb), sizeof(long_ad));
  	udf_write_fi(new_dir, &ncfi, nfi, &nfibh, NULL, NULL);
  
  	/* The old fid may have moved - find it again */
  	ofi = udf_find_entry(old_dir, old_dentry, &ofibh, &ocfi);
  	udf_delete_entry(old_dir, ofi, &ofibh, &ocfi);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1182
  	if (new_inode) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1183
  		new_inode->i_ctime = current_fs_time(new_inode->i_sb);
9a53c3a78   Dave Hansen   [PATCH] r/o bind ...
1184
  		inode_dec_link_count(new_inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1185
1186
1187
  	}
  	old_dir->i_ctime = old_dir->i_mtime = current_fs_time(old_dir->i_sb);
  	mark_inode_dirty(old_dir);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1188
  	if (dir_fi) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1189
1190
  		dir_fi->icb.extLocation = cpu_to_lelb(UDF_I_LOCATION(new_dir));
  		udf_update_tag((char *)dir_fi, (sizeof(struct fileIdentDesc) +
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1191
1192
1193
1194
  						le16_to_cpu(dir_fi->
  							    lengthOfImpUse) +
  						3) & ~3);
  		if (UDF_I_ALLOCTYPE(old_inode) == ICBTAG_FLAG_AD_IN_ICB) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1195
  			mark_inode_dirty(old_inode);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1196
  		} else
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1197
  			mark_buffer_dirty_inode(dir_bh, old_inode);
9a53c3a78   Dave Hansen   [PATCH] r/o bind ...
1198
  		inode_dec_link_count(old_dir);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1199
  		if (new_inode) {
9a53c3a78   Dave Hansen   [PATCH] r/o bind ...
1200
  			inode_dec_link_count(new_inode);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1201
  		} else {
d8c76e6f4   Dave Hansen   [PATCH] r/o bind ...
1202
  			inc_nlink(new_dir);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1203
1204
1205
  			mark_inode_dirty(new_dir);
  		}
  	}
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1206
  	if (ofi) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1207
  		if (ofibh.sbh != ofibh.ebh)
3bf25cb40   Jan Kara   udf: use get_bh()
1208
1209
  			brelse(ofibh.ebh);
  		brelse(ofibh.sbh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1210
1211
1212
  	}
  
  	retval = 0;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1213
        end_rename:
3bf25cb40   Jan Kara   udf: use get_bh()
1214
  	brelse(dir_bh);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1215
  	if (nfi) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1216
  		if (nfibh.sbh != nfibh.ebh)
3bf25cb40   Jan Kara   udf: use get_bh()
1217
1218
  			brelse(nfibh.ebh);
  		brelse(nfibh.sbh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1219
1220
1221
1222
  	}
  	unlock_kernel();
  	return retval;
  }
c5ef1c42c   Arjan van de Ven   [PATCH] mark stru...
1223
  const struct inode_operations udf_dir_inode_operations = {
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1224
1225
1226
1227
1228
1229
1230
1231
1232
  	.lookup = udf_lookup,
  	.create = udf_create,
  	.link = udf_link,
  	.unlink = udf_unlink,
  	.symlink = udf_symlink,
  	.mkdir = udf_mkdir,
  	.rmdir = udf_rmdir,
  	.mknod = udf_mknod,
  	.rename = udf_rename,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1233
  };