Blame view

fs/udf/namei.c 33.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
   * 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>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
30
  #include <linux/buffer_head.h>
e8edc6e03   Alexey Dobriyan   Detach sched.h fr...
31
  #include <linux/sched.h>
f845fced9   Bob Copeland   udf: use crc_itu_...
32
  #include <linux/crc-itu-t.h>
221e583a7   Rasmus Rohde   udf: Make udf exp...
33
  #include <linux/exportfs.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
34

810c1b2e4   Al Viro   udf: fix i_nlink ...
35
  enum { UDF_MAX_LINKS = 0xffff };
391e8bbd3   Al Viro   sanitize const/si...
36
37
  static inline int udf_match(int len1, const unsigned char *name1, int len2,
  			    const unsigned char *name2)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
38
39
40
  {
  	if (len1 != len2)
  		return 0;
28de7948a   Cyrill Gorcunov   UDF: coding style...
41

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
42
43
44
45
  	return !memcmp(name1, name2, len1);
  }
  
  int udf_write_fi(struct inode *inode, struct fileIdentDesc *cfi,
cb00ea352   Cyrill Gorcunov   UDF: coding style...
46
  		 struct fileIdentDesc *sfi, struct udf_fileident_bh *fibh,
4b11111ab   Marcin Slusarz   udf: fix coding s...
47
  		 uint8_t *impuse, uint8_t *fileident)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
48
  {
5ca4e4be8   Pekka Enberg   Remove struct typ...
49
  	uint16_t crclen = fibh->eoffset - fibh->soffset - sizeof(struct tag);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
50
  	uint16_t crc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
51
52
53
54
  	int offset;
  	uint16_t liu = le16_to_cpu(cfi->lengthOfImpUse);
  	uint8_t lfi = cfi->lengthFileIdent;
  	int padlen = fibh->eoffset - fibh->soffset - liu - lfi -
28de7948a   Cyrill Gorcunov   UDF: coding style...
55
  		sizeof(struct fileIdentDesc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
56
  	int adinicb = 0;
c0b344385   Marcin Slusarz   udf: remove UDF_I...
57
  	if (UDF_I(inode)->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
58
59
60
  		adinicb = 1;
  
  	offset = fibh->soffset + sizeof(struct fileIdentDesc);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
61
  	if (impuse) {
28de7948a   Cyrill Gorcunov   UDF: coding style...
62
63
64
  		if (adinicb || (offset + liu < 0)) {
  			memcpy((uint8_t *)sfi->impUse, impuse, liu);
  		} else if (offset >= 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
65
  			memcpy(fibh->ebh->b_data + offset, impuse, liu);
28de7948a   Cyrill Gorcunov   UDF: coding style...
66
67
  		} else {
  			memcpy((uint8_t *)sfi->impUse, impuse, -offset);
4b11111ab   Marcin Slusarz   udf: fix coding s...
68
69
  			memcpy(fibh->ebh->b_data, impuse - offset,
  				liu + offset);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
70
71
72
73
  		}
  	}
  
  	offset += liu;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
74
  	if (fileident) {
28de7948a   Cyrill Gorcunov   UDF: coding style...
75
76
77
  		if (adinicb || (offset + lfi < 0)) {
  			memcpy((uint8_t *)sfi->fileIdent + liu, fileident, lfi);
  		} else if (offset >= 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
78
  			memcpy(fibh->ebh->b_data + offset, fileident, lfi);
28de7948a   Cyrill Gorcunov   UDF: coding style...
79
  		} else {
4b11111ab   Marcin Slusarz   udf: fix coding s...
80
81
82
83
  			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
84
85
86
87
  		}
  	}
  
  	offset += lfi;
28de7948a   Cyrill Gorcunov   UDF: coding style...
88
89
90
  	if (adinicb || (offset + padlen < 0)) {
  		memset((uint8_t *)sfi->padding + liu + lfi, 0x00, padlen);
  	} else if (offset >= 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
91
  		memset(fibh->ebh->b_data + offset, 0x00, padlen);
28de7948a   Cyrill Gorcunov   UDF: coding style...
92
93
  	} else {
  		memset((uint8_t *)sfi->padding + liu + lfi, 0x00, -offset);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
94
95
  		memset(fibh->ebh->b_data, 0x00, padlen + offset);
  	}
5ca4e4be8   Pekka Enberg   Remove struct typ...
96
97
  	crc = crc_itu_t(0, (uint8_t *)cfi + sizeof(struct tag),
  		      sizeof(struct fileIdentDesc) - sizeof(struct tag));
28de7948a   Cyrill Gorcunov   UDF: coding style...
98
99
  
  	if (fibh->sbh == fibh->ebh) {
f845fced9   Bob Copeland   udf: use crc_itu_...
100
  		crc = crc_itu_t(crc, (uint8_t *)sfi->impUse,
5ca4e4be8   Pekka Enberg   Remove struct typ...
101
  			      crclen + sizeof(struct tag) -
f845fced9   Bob Copeland   udf: use crc_itu_...
102
  			      sizeof(struct fileIdentDesc));
28de7948a   Cyrill Gorcunov   UDF: coding style...
103
  	} else if (sizeof(struct fileIdentDesc) >= -fibh->soffset) {
f845fced9   Bob Copeland   udf: use crc_itu_...
104
  		crc = crc_itu_t(crc, fibh->ebh->b_data +
4b11111ab   Marcin Slusarz   udf: fix coding s...
105
106
  					sizeof(struct fileIdentDesc) +
  					fibh->soffset,
5ca4e4be8   Pekka Enberg   Remove struct typ...
107
  			      crclen + sizeof(struct tag) -
f845fced9   Bob Copeland   udf: use crc_itu_...
108
  					sizeof(struct fileIdentDesc));
28de7948a   Cyrill Gorcunov   UDF: coding style...
109
  	} else {
f845fced9   Bob Copeland   udf: use crc_itu_...
110
111
112
  		crc = crc_itu_t(crc, (uint8_t *)sfi->impUse,
  			      -fibh->soffset - sizeof(struct fileIdentDesc));
  		crc = crc_itu_t(crc, fibh->ebh->b_data, fibh->eoffset);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
113
114
115
116
  	}
  
  	cfi->descTag.descCRC = cpu_to_le16(crc);
  	cfi->descTag.descCRCLength = cpu_to_le16(crclen);
3f2587bb2   Marcin Slusarz   udf: create commo...
117
  	cfi->descTag.tagChecksum = udf_tag_checksum(&cfi->descTag);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
118

28de7948a   Cyrill Gorcunov   UDF: coding style...
119
  	if (adinicb || (sizeof(struct fileIdentDesc) <= -fibh->soffset)) {
4b11111ab   Marcin Slusarz   udf: fix coding s...
120
121
  		memcpy((uint8_t *)sfi, (uint8_t *)cfi,
  			sizeof(struct fileIdentDesc));
28de7948a   Cyrill Gorcunov   UDF: coding style...
122
123
124
  	} else {
  		memcpy((uint8_t *)sfi, (uint8_t *)cfi, -fibh->soffset);
  		memcpy(fibh->ebh->b_data, (uint8_t *)cfi - fibh->soffset,
cb00ea352   Cyrill Gorcunov   UDF: coding style...
125
  		       sizeof(struct fileIdentDesc) + fibh->soffset);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
126
  	}
28de7948a   Cyrill Gorcunov   UDF: coding style...
127
  	if (adinicb) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
128
  		mark_inode_dirty(inode);
28de7948a   Cyrill Gorcunov   UDF: coding style...
129
  	} else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
130
131
132
133
134
135
  		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...
136
  static struct fileIdentDesc *udf_find_entry(struct inode *dir,
391e8bbd3   Al Viro   sanitize const/si...
137
  					    const struct qstr *child,
cb00ea352   Cyrill Gorcunov   UDF: coding style...
138
139
  					    struct udf_fileident_bh *fibh,
  					    struct fileIdentDesc *cfi)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
140
  {
cb00ea352   Cyrill Gorcunov   UDF: coding style...
141
  	struct fileIdentDesc *fi = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
142
143
  	loff_t f_pos;
  	int block, flen;
391e8bbd3   Al Viro   sanitize const/si...
144
145
  	unsigned char *fname = NULL;
  	unsigned char *nameptr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
146
147
  	uint8_t lfi;
  	uint16_t liu;
ec471dc48   KAMBAROV, ZAUR   [PATCH] coverity:...
148
  	loff_t size;
5ca4e4be8   Pekka Enberg   Remove struct typ...
149
  	struct kernel_lb_addr eloc;
ff116fc8d   Jan Kara   UDF: introduce st...
150
  	uint32_t elen;
60448b1d6   Jan Kara   udf: use sector_t...
151
  	sector_t offset;
28de7948a   Cyrill Gorcunov   UDF: coding style...
152
  	struct extent_position epos = {};
48d6d8ff7   Marcin Slusarz   udf: cache struct...
153
  	struct udf_inode_info *dinfo = UDF_I(dir);
9fbb76ce0   Al Viro   [PATCH] get rid o...
154
155
  	int isdotdot = child->len == 2 &&
  		child->name[0] == '.' && child->name[1] == '.';
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
156

af793295b   Jan Kara   udf: cleanup dire...
157
158
  	size = udf_ext0_offset(dir) + dir->i_size;
  	f_pos = udf_ext0_offset(dir);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
159

b80697c14   Jan Kara   udf: Remove decla...
160
  	fibh->sbh = fibh->ebh = NULL;
af793295b   Jan Kara   udf: cleanup dire...
161
  	fibh->soffset = fibh->eoffset = f_pos & (dir->i_sb->s_blocksize - 1);
b80697c14   Jan Kara   udf: Remove decla...
162
163
164
165
  	if (dinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) {
  		if (inode_bmap(dir, f_pos >> dir->i_sb->s_blocksize_bits, &epos,
  		    &eloc, &elen, &offset) != (EXT_RECORDED_ALLOCATED >> 30))
  			goto out_err;
97e961fdb   Pekka Enberg   Fix the udf code ...
166
  		block = udf_get_lb_pblock(dir->i_sb, &eloc, offset);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
167
  		if ((++offset << dir->i_sb->s_blocksize_bits) < elen) {
48d6d8ff7   Marcin Slusarz   udf: cache struct...
168
  			if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
5ca4e4be8   Pekka Enberg   Remove struct typ...
169
  				epos.offset -= sizeof(struct short_ad);
48d6d8ff7   Marcin Slusarz   udf: cache struct...
170
  			else if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG)
5ca4e4be8   Pekka Enberg   Remove struct typ...
171
  				epos.offset -= sizeof(struct long_ad);
4b11111ab   Marcin Slusarz   udf: fix coding s...
172
  		} else
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
173
  			offset = 0;
4b11111ab   Marcin Slusarz   udf: fix coding s...
174
  		fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block);
b80697c14   Jan Kara   udf: Remove decla...
175
176
  		if (!fibh->sbh)
  			goto out_err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
177
  	}
b80697c14   Jan Kara   udf: Remove decla...
178
179
180
  	fname = kmalloc(UDF_NAME_LEN, GFP_NOFS);
  	if (!fname)
  		goto out_err;
af793295b   Jan Kara   udf: cleanup dire...
181
  	while (f_pos < size) {
cb00ea352   Cyrill Gorcunov   UDF: coding style...
182
183
  		fi = udf_fileident_read(dir, &f_pos, fibh, cfi, &epos, &eloc,
  					&elen, &offset);
b80697c14   Jan Kara   udf: Remove decla...
184
185
  		if (!fi)
  			goto out_err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
186
187
188
  
  		liu = le16_to_cpu(cfi->lengthOfImpUse);
  		lfi = cfi->lengthFileIdent;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
189
  		if (fibh->sbh == fibh->ebh) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
190
  			nameptr = fi->fileIdent + liu;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
191
  		} else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
192
  			int poffset;	/* Unpaded ending offset */
4b11111ab   Marcin Slusarz   udf: fix coding s...
193
194
  			poffset = fibh->soffset + sizeof(struct fileIdentDesc) +
  					liu + lfi;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
195

4b11111ab   Marcin Slusarz   udf: fix coding s...
196
197
198
199
  			if (poffset >= lfi)
  				nameptr = (uint8_t *)(fibh->ebh->b_data +
  						      poffset - lfi);
  			else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
200
  				nameptr = fname;
4b11111ab   Marcin Slusarz   udf: fix coding s...
201
202
203
204
  				memcpy(nameptr, fi->fileIdent + liu,
  					lfi - poffset);
  				memcpy(nameptr + lfi - poffset,
  					fibh->ebh->b_data, poffset);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
205
206
  			}
  		}
cb00ea352   Cyrill Gorcunov   UDF: coding style...
207
208
  		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
209
210
  				continue;
  		}
cb00ea352   Cyrill Gorcunov   UDF: coding style...
211
212
213
  
  		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
214
215
  				continue;
  		}
221e583a7   Rasmus Rohde   udf: Make udf exp...
216
  		if ((cfi->fileCharacteristics & FID_FILE_CHAR_PARENT) &&
a4264b3f4   Jesper Juhl   UDF: Close small ...
217
218
  		    isdotdot)
  			goto out_ok;
221e583a7   Rasmus Rohde   udf: Make udf exp...
219

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
220
221
  		if (!lfi)
  			continue;
4b11111ab   Marcin Slusarz   udf: fix coding s...
222
  		flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi);
9fbb76ce0   Al Viro   [PATCH] get rid o...
223
  		if (flen && udf_match(flen, fname, child->len, child->name))
b80697c14   Jan Kara   udf: Remove decla...
224
  			goto out_ok;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
225
  	}
28de7948a   Cyrill Gorcunov   UDF: coding style...
226

b80697c14   Jan Kara   udf: Remove decla...
227
228
  out_err:
  	fi = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
229
  	if (fibh->sbh != fibh->ebh)
3bf25cb40   Jan Kara   udf: use get_bh()
230
231
  		brelse(fibh->ebh);
  	brelse(fibh->sbh);
b80697c14   Jan Kara   udf: Remove decla...
232
  out_ok:
3bf25cb40   Jan Kara   udf: use get_bh()
233
  	brelse(epos.bh);
b80697c14   Jan Kara   udf: Remove decla...
234
  	kfree(fname);
28de7948a   Cyrill Gorcunov   UDF: coding style...
235

b80697c14   Jan Kara   udf: Remove decla...
236
  	return fi;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
237
  }
cb00ea352   Cyrill Gorcunov   UDF: coding style...
238
239
  static struct dentry *udf_lookup(struct inode *dir, struct dentry *dentry,
  				 struct nameidata *nd)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
240
241
  {
  	struct inode *inode = NULL;
db9a369ec   Jayachandran C   [PATCH] UDF: Fix ...
242
  	struct fileIdentDesc cfi;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
243
  	struct udf_fileident_bh fibh;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
244
  	if (dentry->d_name.len > UDF_NAME_LEN - 2)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
245
  		return ERR_PTR(-ENAMETOOLONG);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
246
247
  #ifdef UDF_RECOVERY
  	/* temporary shorthand for specifying files by inode number */
cb00ea352   Cyrill Gorcunov   UDF: coding style...
248
  	if (!strncmp(dentry->d_name.name, ".B=", 3)) {
5ca4e4be8   Pekka Enberg   Remove struct typ...
249
  		struct kernel_lb_addr lb = {
28de7948a   Cyrill Gorcunov   UDF: coding style...
250
  			.logicalBlockNum = 0,
4b11111ab   Marcin Slusarz   udf: fix coding s...
251
252
253
  			.partitionReferenceNum =
  				simple_strtoul(dentry->d_name.name + 3,
  						NULL, 0),
28de7948a   Cyrill Gorcunov   UDF: coding style...
254
  		};
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
255
  		inode = udf_iget(dir->i_sb, lb);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
256
  		if (!inode) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
257
258
  			return ERR_PTR(-EACCES);
  		}
4b11111ab   Marcin Slusarz   udf: fix coding s...
259
  	} else
28de7948a   Cyrill Gorcunov   UDF: coding style...
260
  #endif /* UDF_RECOVERY */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
261

9fbb76ce0   Al Viro   [PATCH] get rid o...
262
  	if (udf_find_entry(dir, &dentry->d_name, &fibh, &cfi)) {
97e961fdb   Pekka Enberg   Fix the udf code ...
263
  		struct kernel_lb_addr loc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
264
  		if (fibh.sbh != fibh.ebh)
3bf25cb40   Jan Kara   udf: use get_bh()
265
266
  			brelse(fibh.ebh);
  		brelse(fibh.sbh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
267

97e961fdb   Pekka Enberg   Fix the udf code ...
268
269
  		loc = lelb_to_cpu(cfi.icb.extLocation);
  		inode = udf_iget(dir->i_sb, &loc);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
270
  		if (!inode) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
271
272
273
  			return ERR_PTR(-EACCES);
  		}
  	}
28de7948a   Cyrill Gorcunov   UDF: coding style...
274

221e583a7   Rasmus Rohde   udf: Make udf exp...
275
  	return d_splice_alias(inode, dentry);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
276
  }
cb00ea352   Cyrill Gorcunov   UDF: coding style...
277
278
279
280
  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
281
  {
6c79e987d   Marcin Slusarz   udf: remove some ...
282
  	struct super_block *sb = dir->i_sb;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
283
  	struct fileIdentDesc *fi = NULL;
391e8bbd3   Al Viro   sanitize const/si...
284
  	unsigned char *name = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
285
286
  	int namelen;
  	loff_t f_pos;
af793295b   Jan Kara   udf: cleanup dire...
287
  	loff_t size = udf_ext0_offset(dir) + dir->i_size;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
288
289
290
291
  	int nfidlen;
  	uint8_t lfi;
  	uint16_t liu;
  	int block;
5ca4e4be8   Pekka Enberg   Remove struct typ...
292
  	struct kernel_lb_addr eloc;
9afadc4b1   Jan Kara   udf: Fix memory c...
293
  	uint32_t elen = 0;
60448b1d6   Jan Kara   udf: use sector_t...
294
  	sector_t offset;
28de7948a   Cyrill Gorcunov   UDF: coding style...
295
  	struct extent_position epos = {};
48d6d8ff7   Marcin Slusarz   udf: cache struct...
296
  	struct udf_inode_info *dinfo;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
297

b80697c14   Jan Kara   udf: Remove decla...
298
299
300
301
302
303
  	fibh->sbh = fibh->ebh = NULL;
  	name = kmalloc(UDF_NAME_LEN, GFP_NOFS);
  	if (!name) {
  		*err = -ENOMEM;
  		goto out_err;
  	}
cb00ea352   Cyrill Gorcunov   UDF: coding style...
304
305
  	if (dentry) {
  		if (!dentry->d_name.len) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
306
  			*err = -EINVAL;
b80697c14   Jan Kara   udf: Remove decla...
307
  			goto out_err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
308
  		}
4b11111ab   Marcin Slusarz   udf: fix coding s...
309
310
311
  		namelen = udf_put_filename(sb, dentry->d_name.name, name,
  						 dentry->d_name.len);
  		if (!namelen) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
312
  			*err = -ENAMETOOLONG;
b80697c14   Jan Kara   udf: Remove decla...
313
  			goto out_err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
314
  		}
28de7948a   Cyrill Gorcunov   UDF: coding style...
315
  	} else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
316
  		namelen = 0;
28de7948a   Cyrill Gorcunov   UDF: coding style...
317
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
318
319
  
  	nfidlen = (sizeof(struct fileIdentDesc) + namelen + 3) & ~3;
af793295b   Jan Kara   udf: cleanup dire...
320
  	f_pos = udf_ext0_offset(dir);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
321

af793295b   Jan Kara   udf: cleanup dire...
322
  	fibh->soffset = fibh->eoffset = f_pos & (dir->i_sb->s_blocksize - 1);
48d6d8ff7   Marcin Slusarz   udf: cache struct...
323
  	dinfo = UDF_I(dir);
b80697c14   Jan Kara   udf: Remove decla...
324
325
326
327
  	if (dinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) {
  		if (inode_bmap(dir, f_pos >> dir->i_sb->s_blocksize_bits, &epos,
  		    &eloc, &elen, &offset) != (EXT_RECORDED_ALLOCATED >> 30)) {
  			block = udf_get_lb_pblock(dir->i_sb,
97e961fdb   Pekka Enberg   Fix the udf code ...
328
  					&dinfo->i_location, 0);
b80697c14   Jan Kara   udf: Remove decla...
329
330
331
  			fibh->soffset = fibh->eoffset = sb->s_blocksize;
  			goto add;
  		}
97e961fdb   Pekka Enberg   Fix the udf code ...
332
  		block = udf_get_lb_pblock(dir->i_sb, &eloc, offset);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
333
  		if ((++offset << dir->i_sb->s_blocksize_bits) < elen) {
48d6d8ff7   Marcin Slusarz   udf: cache struct...
334
  			if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
5ca4e4be8   Pekka Enberg   Remove struct typ...
335
  				epos.offset -= sizeof(struct short_ad);
48d6d8ff7   Marcin Slusarz   udf: cache struct...
336
  			else if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG)
5ca4e4be8   Pekka Enberg   Remove struct typ...
337
  				epos.offset -= sizeof(struct long_ad);
4b11111ab   Marcin Slusarz   udf: fix coding s...
338
  		} else
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
339
  			offset = 0;
4b11111ab   Marcin Slusarz   udf: fix coding s...
340
341
  		fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block);
  		if (!fibh->sbh) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
342
  			*err = -EIO;
b80697c14   Jan Kara   udf: Remove decla...
343
  			goto out_err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
344
  		}
48d6d8ff7   Marcin Slusarz   udf: cache struct...
345
  		block = dinfo->i_location.logicalBlockNum;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
346
  	}
af793295b   Jan Kara   udf: cleanup dire...
347
  	while (f_pos < size) {
cb00ea352   Cyrill Gorcunov   UDF: coding style...
348
349
  		fi = udf_fileident_read(dir, &f_pos, fibh, cfi, &epos, &eloc,
  					&elen, &offset);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
350

cb00ea352   Cyrill Gorcunov   UDF: coding style...
351
  		if (!fi) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
352
  			*err = -EIO;
b80697c14   Jan Kara   udf: Remove decla...
353
  			goto out_err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
354
355
356
357
  		}
  
  		liu = le16_to_cpu(cfi->lengthOfImpUse);
  		lfi = cfi->lengthFileIdent;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
358
  		if ((cfi->fileCharacteristics & FID_FILE_CHAR_DELETED) != 0) {
4b11111ab   Marcin Slusarz   udf: fix coding s...
359
360
  			if (((sizeof(struct fileIdentDesc) +
  					liu + lfi + 3) & ~3) == nfidlen) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
361
362
363
364
365
  				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);
4b11111ab   Marcin Slusarz   udf: fix coding s...
366
367
  				if (!udf_write_fi(dir, cfi, fi, fibh, NULL,
  						  name))
b80697c14   Jan Kara   udf: Remove decla...
368
  					goto out_ok;
4b11111ab   Marcin Slusarz   udf: fix coding s...
369
  				else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
370
  					*err = -EIO;
b80697c14   Jan Kara   udf: Remove decla...
371
  					goto out_err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
372
373
374
  				}
  			}
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
375
  	}
28de7948a   Cyrill Gorcunov   UDF: coding style...
376
  add:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
377
  	f_pos += nfidlen;
48d6d8ff7   Marcin Slusarz   udf: cache struct...
378
  	if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB &&
cb00ea352   Cyrill Gorcunov   UDF: coding style...
379
  	    sb->s_blocksize - fibh->eoffset < nfidlen) {
3bf25cb40   Jan Kara   udf: use get_bh()
380
  		brelse(epos.bh);
ff116fc8d   Jan Kara   UDF: introduce st...
381
  		epos.bh = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
382
383
  		fibh->soffset -= udf_ext0_offset(dir);
  		fibh->eoffset -= udf_ext0_offset(dir);
af793295b   Jan Kara   udf: cleanup dire...
384
  		f_pos -= udf_ext0_offset(dir);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
385
  		if (fibh->sbh != fibh->ebh)
3bf25cb40   Jan Kara   udf: use get_bh()
386
387
  			brelse(fibh->ebh);
  		brelse(fibh->sbh);
4b11111ab   Marcin Slusarz   udf: fix coding s...
388
389
390
  		fibh->sbh = fibh->ebh =
  				udf_expand_dir_adinicb(dir, &block, err);
  		if (!fibh->sbh)
b80697c14   Jan Kara   udf: Remove decla...
391
  			goto out_err;
48d6d8ff7   Marcin Slusarz   udf: cache struct...
392
  		epos.block = dinfo->i_location;
ff116fc8d   Jan Kara   UDF: introduce st...
393
  		epos.offset = udf_file_entry_alloc_offset(dir);
05343c4f2   Jan Kara   udf: fix adding e...
394
395
  		/* Load extent udf_expand_dir_adinicb() has created */
  		udf_current_aext(dir, &epos, &eloc, &elen, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
396
  	}
2c948b3f8   Jan Kara   udf: Avoid IO in ...
397
  	/* Entry fits into current block? */
cb00ea352   Cyrill Gorcunov   UDF: coding style...
398
  	if (sb->s_blocksize - fibh->eoffset >= nfidlen) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
399
400
  		fibh->soffset = fibh->eoffset;
  		fibh->eoffset += nfidlen;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
401
  		if (fibh->sbh != fibh->ebh) {
3bf25cb40   Jan Kara   udf: use get_bh()
402
  			brelse(fibh->sbh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
403
404
  			fibh->sbh = fibh->ebh;
  		}
48d6d8ff7   Marcin Slusarz   udf: cache struct...
405
406
  		if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
  			block = dinfo->i_location.logicalBlockNum;
4b11111ab   Marcin Slusarz   udf: fix coding s...
407
  			fi = (struct fileIdentDesc *)
48d6d8ff7   Marcin Slusarz   udf: cache struct...
408
  					(dinfo->i_ext.i_data +
c0b344385   Marcin Slusarz   udf: remove UDF_I...
409
  					 fibh->soffset -
4b11111ab   Marcin Slusarz   udf: fix coding s...
410
  					 udf_ext0_offset(dir) +
48d6d8ff7   Marcin Slusarz   udf: cache struct...
411
  					 dinfo->i_lenEAttr);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
412
  		} else {
4b11111ab   Marcin Slusarz   udf: fix coding s...
413
414
415
416
417
  			block = eloc.logicalBlockNum +
  					((elen - 1) >>
  						dir->i_sb->s_blocksize_bits);
  			fi = (struct fileIdentDesc *)
  				(fibh->sbh->b_data + fibh->soffset);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
418
  		}
cb00ea352   Cyrill Gorcunov   UDF: coding style...
419
  	} else {
2c948b3f8   Jan Kara   udf: Avoid IO in ...
420
421
422
423
424
425
426
427
428
  		/* Round up last extent in the file */
  		elen = (elen + sb->s_blocksize - 1) & ~(sb->s_blocksize - 1);
  		if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
  			epos.offset -= sizeof(struct short_ad);
  		else if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG)
  			epos.offset -= sizeof(struct long_ad);
  		udf_write_aext(dir, &epos, &eloc, elen, 1);
  		dinfo->i_lenExtents = (dinfo->i_lenExtents + sb->s_blocksize
  					- 1) & ~(sb->s_blocksize - 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
429
430
  		fibh->soffset = fibh->eoffset - sb->s_blocksize;
  		fibh->eoffset += nfidlen - sb->s_blocksize;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
431
  		if (fibh->sbh != fibh->ebh) {
3bf25cb40   Jan Kara   udf: use get_bh()
432
  			brelse(fibh->sbh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
433
434
435
436
  			fibh->sbh = fibh->ebh;
  		}
  
  		block = eloc.logicalBlockNum + ((elen - 1) >>
cb00ea352   Cyrill Gorcunov   UDF: coding style...
437
  						dir->i_sb->s_blocksize_bits);
4b11111ab   Marcin Slusarz   udf: fix coding s...
438
  		fibh->ebh = udf_bread(dir,
af793295b   Jan Kara   udf: cleanup dire...
439
  				f_pos >> dir->i_sb->s_blocksize_bits, 1, err);
b80697c14   Jan Kara   udf: Remove decla...
440
441
  		if (!fibh->ebh)
  			goto out_err;
4651c5900   Jan Kara   udf: Fix director...
442
443
444
445
446
  		/* Extents could have been merged, invalidate our position */
  		brelse(epos.bh);
  		epos.bh = NULL;
  		epos.block = dinfo->i_location;
  		epos.offset = udf_file_entry_alloc_offset(dir);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
447

28de7948a   Cyrill Gorcunov   UDF: coding style...
448
  		if (!fibh->soffset) {
4651c5900   Jan Kara   udf: Fix director...
449
450
451
452
453
  			/* Find the freshly allocated block */
  			while (udf_next_aext(dir, &epos, &eloc, &elen, 1) ==
  				(EXT_RECORDED_ALLOCATED >> 30))
  				;
  			block = eloc.logicalBlockNum + ((elen - 1) >>
28de7948a   Cyrill Gorcunov   UDF: coding style...
454
  					dir->i_sb->s_blocksize_bits);
3bf25cb40   Jan Kara   udf: use get_bh()
455
  			brelse(fibh->sbh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
456
457
  			fibh->sbh = fibh->ebh;
  			fi = (struct fileIdentDesc *)(fibh->sbh->b_data);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
458
  		} else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
459
  			fi = (struct fileIdentDesc *)
4b11111ab   Marcin Slusarz   udf: fix coding s...
460
461
  				(fibh->sbh->b_data + sb->s_blocksize +
  					fibh->soffset);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
462
463
464
465
  		}
  	}
  
  	memset(cfi, 0, sizeof(struct fileIdentDesc));
6c79e987d   Marcin Slusarz   udf: remove some ...
466
  	if (UDF_SB(sb)->s_udfrev >= 0x0200)
4b11111ab   Marcin Slusarz   udf: fix coding s...
467
  		udf_new_tag((char *)cfi, TAG_IDENT_FID, 3, 1, block,
5ca4e4be8   Pekka Enberg   Remove struct typ...
468
  			    sizeof(struct tag));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
469
  	else
4b11111ab   Marcin Slusarz   udf: fix coding s...
470
  		udf_new_tag((char *)cfi, TAG_IDENT_FID, 2, 1, block,
5ca4e4be8   Pekka Enberg   Remove struct typ...
471
  			    sizeof(struct tag));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
472
473
474
  	cfi->fileVersionNum = cpu_to_le16(1);
  	cfi->lengthFileIdent = namelen;
  	cfi->lengthOfImpUse = cpu_to_le16(0);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
475
  	if (!udf_write_fi(dir, cfi, fi, fibh, NULL, name)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
476
  		dir->i_size += nfidlen;
48d6d8ff7   Marcin Slusarz   udf: cache struct...
477
478
  		if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
  			dinfo->i_lenAlloc += nfidlen;
2c948b3f8   Jan Kara   udf: Avoid IO in ...
479
480
481
482
483
484
485
486
487
488
489
490
491
  		else {
  			/* Find the last extent and truncate it to proper size */
  			while (udf_next_aext(dir, &epos, &eloc, &elen, 1) ==
  				(EXT_RECORDED_ALLOCATED >> 30))
  				;
  			elen -= dinfo->i_lenExtents - dir->i_size;
  			if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
  				epos.offset -= sizeof(struct short_ad);
  			else if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG)
  				epos.offset -= sizeof(struct long_ad);
  			udf_write_aext(dir, &epos, &eloc, elen, 1);
  			dinfo->i_lenExtents = dir->i_size;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
492
  		mark_inode_dirty(dir);
b80697c14   Jan Kara   udf: Remove decla...
493
  		goto out_ok;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
494
  	} else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
495
  		*err = -EIO;
b80697c14   Jan Kara   udf: Remove decla...
496
  		goto out_err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
497
  	}
b80697c14   Jan Kara   udf: Remove decla...
498
499
500
501
502
503
504
505
506
507
  
  out_err:
  	fi = NULL;
  	if (fibh->sbh != fibh->ebh)
  		brelse(fibh->ebh);
  	brelse(fibh->sbh);
  out_ok:
  	brelse(epos.bh);
  	kfree(name);
  	return fi;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
508
509
510
  }
  
  static int udf_delete_entry(struct inode *inode, struct fileIdentDesc *fi,
cb00ea352   Cyrill Gorcunov   UDF: coding style...
511
512
  			    struct udf_fileident_bh *fibh,
  			    struct fileIdentDesc *cfi)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
513
514
  {
  	cfi->fileCharacteristics |= FID_FILE_CHAR_DELETED;
28de7948a   Cyrill Gorcunov   UDF: coding style...
515

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
516
  	if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT))
5ca4e4be8   Pekka Enberg   Remove struct typ...
517
  		memset(&(cfi->icb), 0x00, sizeof(struct long_ad));
28de7948a   Cyrill Gorcunov   UDF: coding style...
518

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
519
520
  	return udf_write_fi(inode, cfi, fi, fibh, NULL, NULL);
  }
4acdaf27e   Al Viro   switch ->create()...
521
  static int udf_create(struct inode *dir, struct dentry *dentry, umode_t mode,
cb00ea352   Cyrill Gorcunov   UDF: coding style...
522
  		      struct nameidata *nd)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
523
524
525
526
527
  {
  	struct udf_fileident_bh fibh;
  	struct inode *inode;
  	struct fileIdentDesc cfi, *fi;
  	int err;
48d6d8ff7   Marcin Slusarz   udf: cache struct...
528
  	struct udf_inode_info *iinfo;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
529

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
530
  	inode = udf_new_inode(dir, mode, &err);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
531
  	if (!inode) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
532
533
  		return err;
  	}
48d6d8ff7   Marcin Slusarz   udf: cache struct...
534
535
  	iinfo = UDF_I(inode);
  	if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
536
537
538
539
540
  		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;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
541
  	mark_inode_dirty(inode);
4b11111ab   Marcin Slusarz   udf: fix coding s...
542
543
  	fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err);
  	if (!fi) {
6d6b77f16   Miklos Szeredi   filesystems: add ...
544
  		inode_dec_link_count(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
545
  		iput(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
546
547
548
  		return err;
  	}
  	cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
48d6d8ff7   Marcin Slusarz   udf: cache struct...
549
  	cfi.icb.extLocation = cpu_to_lelb(iinfo->i_location);
28de7948a   Cyrill Gorcunov   UDF: coding style...
550
  	*(__le32 *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse =
48d6d8ff7   Marcin Slusarz   udf: cache struct...
551
  		cpu_to_le32(iinfo->i_unique & 0x00000000FFFFFFFFUL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
552
  	udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL);
c0b344385   Marcin Slusarz   udf: remove UDF_I...
553
  	if (UDF_I(dir)->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
554
  		mark_inode_dirty(dir);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
555
  	if (fibh.sbh != fibh.ebh)
3bf25cb40   Jan Kara   udf: use get_bh()
556
557
  		brelse(fibh.ebh);
  	brelse(fibh.sbh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
558
  	d_instantiate(dentry, inode);
28de7948a   Cyrill Gorcunov   UDF: coding style...
559

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
560
561
  	return 0;
  }
1a67aafb5   Al Viro   switch ->mknod() ...
562
  static int udf_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
cb00ea352   Cyrill Gorcunov   UDF: coding style...
563
  		     dev_t rdev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
564
  {
cb00ea352   Cyrill Gorcunov   UDF: coding style...
565
  	struct inode *inode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
566
567
568
  	struct udf_fileident_bh fibh;
  	struct fileIdentDesc cfi, *fi;
  	int err;
48d6d8ff7   Marcin Slusarz   udf: cache struct...
569
  	struct udf_inode_info *iinfo;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
570
571
572
  
  	if (!old_valid_dev(rdev))
  		return -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
573
574
575
576
  	err = -EIO;
  	inode = udf_new_inode(dir, mode, &err);
  	if (!inode)
  		goto out;
48d6d8ff7   Marcin Slusarz   udf: cache struct...
577
  	iinfo = UDF_I(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
578
  	init_special_inode(inode, mode, rdev);
4b11111ab   Marcin Slusarz   udf: fix coding s...
579
580
  	fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err);
  	if (!fi) {
6d6b77f16   Miklos Szeredi   filesystems: add ...
581
  		inode_dec_link_count(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
582
  		iput(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
583
584
585
  		return err;
  	}
  	cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
48d6d8ff7   Marcin Slusarz   udf: cache struct...
586
  	cfi.icb.extLocation = cpu_to_lelb(iinfo->i_location);
28de7948a   Cyrill Gorcunov   UDF: coding style...
587
  	*(__le32 *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse =
48d6d8ff7   Marcin Slusarz   udf: cache struct...
588
  		cpu_to_le32(iinfo->i_unique & 0x00000000FFFFFFFFUL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
589
  	udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL);
c0b344385   Marcin Slusarz   udf: remove UDF_I...
590
  	if (UDF_I(dir)->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
591
  		mark_inode_dirty(dir);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
592
593
594
  	mark_inode_dirty(inode);
  
  	if (fibh.sbh != fibh.ebh)
3bf25cb40   Jan Kara   udf: use get_bh()
595
596
  		brelse(fibh.ebh);
  	brelse(fibh.sbh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
597
598
  	d_instantiate(dentry, inode);
  	err = 0;
28de7948a   Cyrill Gorcunov   UDF: coding style...
599
600
  
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
601
602
  	return err;
  }
18bb1db3e   Al Viro   switch vfs_mkdir(...
603
  static int udf_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
604
  {
cb00ea352   Cyrill Gorcunov   UDF: coding style...
605
  	struct inode *inode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
606
607
608
  	struct udf_fileident_bh fibh;
  	struct fileIdentDesc cfi, *fi;
  	int err;
48d6d8ff7   Marcin Slusarz   udf: cache struct...
609
610
  	struct udf_inode_info *dinfo = UDF_I(dir);
  	struct udf_inode_info *iinfo;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
611

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
612
  	err = -EMLINK;
810c1b2e4   Al Viro   udf: fix i_nlink ...
613
  	if (dir->i_nlink >= UDF_MAX_LINKS)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
614
615
616
  		goto out;
  
  	err = -EIO;
a6c5a0342   Dmitry Monakhov   udf: replace inod...
617
  	inode = udf_new_inode(dir, S_IFDIR | mode, &err);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
618
619
  	if (!inode)
  		goto out;
48d6d8ff7   Marcin Slusarz   udf: cache struct...
620
  	iinfo = UDF_I(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
621
622
  	inode->i_op = &udf_dir_inode_operations;
  	inode->i_fop = &udf_dir_operations;
4b11111ab   Marcin Slusarz   udf: fix coding s...
623
624
  	fi = udf_add_entry(inode, NULL, &fibh, &cfi, &err);
  	if (!fi) {
6d6b77f16   Miklos Szeredi   filesystems: add ...
625
  		inode_dec_link_count(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
626
627
628
  		iput(inode);
  		goto out;
  	}
bfe868486   Miklos Szeredi   filesystems: add ...
629
  	set_nlink(inode, 2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
630
  	cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
48d6d8ff7   Marcin Slusarz   udf: cache struct...
631
  	cfi.icb.extLocation = cpu_to_lelb(dinfo->i_location);
28de7948a   Cyrill Gorcunov   UDF: coding style...
632
  	*(__le32 *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse =
48d6d8ff7   Marcin Slusarz   udf: cache struct...
633
  		cpu_to_le32(dinfo->i_unique & 0x00000000FFFFFFFFUL);
4b11111ab   Marcin Slusarz   udf: fix coding s...
634
635
  	cfi.fileCharacteristics =
  			FID_FILE_CHAR_DIRECTORY | FID_FILE_CHAR_PARENT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
636
  	udf_write_fi(inode, &cfi, fi, &fibh, NULL, NULL);
3bf25cb40   Jan Kara   udf: use get_bh()
637
  	brelse(fibh.sbh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
638
  	mark_inode_dirty(inode);
4b11111ab   Marcin Slusarz   udf: fix coding s...
639
640
  	fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err);
  	if (!fi) {
6d6b77f16   Miklos Szeredi   filesystems: add ...
641
  		clear_nlink(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
642
643
644
645
646
  		mark_inode_dirty(inode);
  		iput(inode);
  		goto out;
  	}
  	cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
48d6d8ff7   Marcin Slusarz   udf: cache struct...
647
  	cfi.icb.extLocation = cpu_to_lelb(iinfo->i_location);
28de7948a   Cyrill Gorcunov   UDF: coding style...
648
  	*(__le32 *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse =
48d6d8ff7   Marcin Slusarz   udf: cache struct...
649
  		cpu_to_le32(iinfo->i_unique & 0x00000000FFFFFFFFUL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
650
651
  	cfi.fileCharacteristics |= FID_FILE_CHAR_DIRECTORY;
  	udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL);
d8c76e6f4   Dave Hansen   [PATCH] r/o bind ...
652
  	inc_nlink(dir);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
653
654
655
  	mark_inode_dirty(dir);
  	d_instantiate(dentry, inode);
  	if (fibh.sbh != fibh.ebh)
3bf25cb40   Jan Kara   udf: use get_bh()
656
657
  		brelse(fibh.ebh);
  	brelse(fibh.sbh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
658
  	err = 0;
28de7948a   Cyrill Gorcunov   UDF: coding style...
659
660
  
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
661
662
663
664
665
666
667
668
  	return err;
  }
  
  static int empty_dir(struct inode *dir)
  {
  	struct fileIdentDesc *fi, cfi;
  	struct udf_fileident_bh fibh;
  	loff_t f_pos;
af793295b   Jan Kara   udf: cleanup dire...
669
  	loff_t size = udf_ext0_offset(dir) + dir->i_size;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
670
  	int block;
5ca4e4be8   Pekka Enberg   Remove struct typ...
671
  	struct kernel_lb_addr eloc;
ff116fc8d   Jan Kara   UDF: introduce st...
672
  	uint32_t elen;
60448b1d6   Jan Kara   udf: use sector_t...
673
  	sector_t offset;
28de7948a   Cyrill Gorcunov   UDF: coding style...
674
  	struct extent_position epos = {};
48d6d8ff7   Marcin Slusarz   udf: cache struct...
675
  	struct udf_inode_info *dinfo = UDF_I(dir);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
676

af793295b   Jan Kara   udf: cleanup dire...
677
678
  	f_pos = udf_ext0_offset(dir);
  	fibh.soffset = fibh.eoffset = f_pos & (dir->i_sb->s_blocksize - 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
679

48d6d8ff7   Marcin Slusarz   udf: cache struct...
680
  	if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
681
  		fibh.sbh = fibh.ebh = NULL;
af793295b   Jan Kara   udf: cleanup dire...
682
  	else if (inode_bmap(dir, f_pos >> dir->i_sb->s_blocksize_bits,
4b11111ab   Marcin Slusarz   udf: fix coding s...
683
684
  			      &epos, &eloc, &elen, &offset) ==
  					(EXT_RECORDED_ALLOCATED >> 30)) {
97e961fdb   Pekka Enberg   Fix the udf code ...
685
  		block = udf_get_lb_pblock(dir->i_sb, &eloc, offset);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
686
  		if ((++offset << dir->i_sb->s_blocksize_bits) < elen) {
48d6d8ff7   Marcin Slusarz   udf: cache struct...
687
  			if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
5ca4e4be8   Pekka Enberg   Remove struct typ...
688
  				epos.offset -= sizeof(struct short_ad);
48d6d8ff7   Marcin Slusarz   udf: cache struct...
689
  			else if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG)
5ca4e4be8   Pekka Enberg   Remove struct typ...
690
  				epos.offset -= sizeof(struct long_ad);
4b11111ab   Marcin Slusarz   udf: fix coding s...
691
  		} else
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
692
  			offset = 0;
4b11111ab   Marcin Slusarz   udf: fix coding s...
693
694
  		fibh.sbh = fibh.ebh = udf_tread(dir->i_sb, block);
  		if (!fibh.sbh) {
3bf25cb40   Jan Kara   udf: use get_bh()
695
  			brelse(epos.bh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
696
697
  			return 0;
  		}
cb00ea352   Cyrill Gorcunov   UDF: coding style...
698
  	} else {
3bf25cb40   Jan Kara   udf: use get_bh()
699
  		brelse(epos.bh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
700
701
  		return 0;
  	}
af793295b   Jan Kara   udf: cleanup dire...
702
  	while (f_pos < size) {
cb00ea352   Cyrill Gorcunov   UDF: coding style...
703
704
  		fi = udf_fileident_read(dir, &f_pos, &fibh, &cfi, &epos, &eloc,
  					&elen, &offset);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
705
  		if (!fi) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
706
  			if (fibh.sbh != fibh.ebh)
3bf25cb40   Jan Kara   udf: use get_bh()
707
708
709
  				brelse(fibh.ebh);
  			brelse(fibh.sbh);
  			brelse(epos.bh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
710
711
  			return 0;
  		}
28de7948a   Cyrill Gorcunov   UDF: coding style...
712
713
  		if (cfi.lengthFileIdent &&
  		    (cfi.fileCharacteristics & FID_FILE_CHAR_DELETED) == 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
714
  			if (fibh.sbh != fibh.ebh)
3bf25cb40   Jan Kara   udf: use get_bh()
715
716
717
  				brelse(fibh.ebh);
  			brelse(fibh.sbh);
  			brelse(epos.bh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
718
719
720
  			return 0;
  		}
  	}
28de7948a   Cyrill Gorcunov   UDF: coding style...
721

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
722
  	if (fibh.sbh != fibh.ebh)
3bf25cb40   Jan Kara   udf: use get_bh()
723
724
725
  		brelse(fibh.ebh);
  	brelse(fibh.sbh);
  	brelse(epos.bh);
28de7948a   Cyrill Gorcunov   UDF: coding style...
726

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
727
728
  	return 1;
  }
cb00ea352   Cyrill Gorcunov   UDF: coding style...
729
  static int udf_rmdir(struct inode *dir, struct dentry *dentry)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
730
731
  {
  	int retval;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
732
  	struct inode *inode = dentry->d_inode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
733
734
  	struct udf_fileident_bh fibh;
  	struct fileIdentDesc *fi, cfi;
5ca4e4be8   Pekka Enberg   Remove struct typ...
735
  	struct kernel_lb_addr tloc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
736
737
  
  	retval = -ENOENT;
9fbb76ce0   Al Viro   [PATCH] get rid o...
738
  	fi = udf_find_entry(dir, &dentry->d_name, &fibh, &cfi);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
739
740
741
742
743
  	if (!fi)
  		goto out;
  
  	retval = -EIO;
  	tloc = lelb_to_cpu(cfi.icb.extLocation);
97e961fdb   Pekka Enberg   Fix the udf code ...
744
  	if (udf_get_lb_pblock(dir->i_sb, &tloc, 0) != inode->i_ino)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
745
746
747
748
749
750
751
752
  		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)
a40ecd7b3   Joe Perches   udf: Rename udf_w...
753
754
755
  		udf_warn(inode->i_sb, "empty directory has nlink != 2 (%d)
  ",
  			 inode->i_nlink);
ce71ec368   Dave Hansen   [PATCH] r/o bind ...
756
  	clear_nlink(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
757
  	inode->i_size = 0;
c007c06e3   Stephen Mollett   udf: decrement co...
758
  	inode_dec_link_count(dir);
4b11111ab   Marcin Slusarz   udf: fix coding s...
759
760
  	inode->i_ctime = dir->i_ctime = dir->i_mtime =
  						current_fs_time(dir->i_sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
761
  	mark_inode_dirty(dir);
28de7948a   Cyrill Gorcunov   UDF: coding style...
762
  end_rmdir:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
763
  	if (fibh.sbh != fibh.ebh)
3bf25cb40   Jan Kara   udf: use get_bh()
764
765
  		brelse(fibh.ebh);
  	brelse(fibh.sbh);
28de7948a   Cyrill Gorcunov   UDF: coding style...
766
767
  
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
768
769
  	return retval;
  }
cb00ea352   Cyrill Gorcunov   UDF: coding style...
770
  static int udf_unlink(struct inode *dir, struct dentry *dentry)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
771
772
  {
  	int retval;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
773
  	struct inode *inode = dentry->d_inode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
774
775
776
  	struct udf_fileident_bh fibh;
  	struct fileIdentDesc *fi;
  	struct fileIdentDesc cfi;
5ca4e4be8   Pekka Enberg   Remove struct typ...
777
  	struct kernel_lb_addr tloc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
778
779
  
  	retval = -ENOENT;
9fbb76ce0   Al Viro   [PATCH] get rid o...
780
  	fi = udf_find_entry(dir, &dentry->d_name, &fibh, &cfi);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
781
782
783
784
785
  	if (!fi)
  		goto out;
  
  	retval = -EIO;
  	tloc = lelb_to_cpu(cfi.icb.extLocation);
97e961fdb   Pekka Enberg   Fix the udf code ...
786
  	if (udf_get_lb_pblock(dir->i_sb, &tloc, 0) != inode->i_ino)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
787
  		goto end_unlink;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
788
  	if (!inode->i_nlink) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
789
790
  		udf_debug("Deleting nonexistent file (%lu), %d
  ",
cb00ea352   Cyrill Gorcunov   UDF: coding style...
791
  			  inode->i_ino, inode->i_nlink);
bfe868486   Miklos Szeredi   filesystems: add ...
792
  		set_nlink(inode, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
793
794
795
796
797
798
  	}
  	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 ...
799
  	inode_dec_link_count(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
800
801
  	inode->i_ctime = dir->i_ctime;
  	retval = 0;
28de7948a   Cyrill Gorcunov   UDF: coding style...
802
  end_unlink:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
803
  	if (fibh.sbh != fibh.ebh)
3bf25cb40   Jan Kara   udf: use get_bh()
804
805
  		brelse(fibh.ebh);
  	brelse(fibh.sbh);
28de7948a   Cyrill Gorcunov   UDF: coding style...
806
807
  
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
808
809
  	return retval;
  }
cb00ea352   Cyrill Gorcunov   UDF: coding style...
810
811
  static int udf_symlink(struct inode *dir, struct dentry *dentry,
  		       const char *symname)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
812
  {
cb00ea352   Cyrill Gorcunov   UDF: coding style...
813
  	struct inode *inode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
814
  	struct pathComponent *pc;
391e8bbd3   Al Viro   sanitize const/si...
815
  	const char *compstart;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
816
  	struct udf_fileident_bh fibh;
28de7948a   Cyrill Gorcunov   UDF: coding style...
817
  	struct extent_position epos = {};
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
818
819
820
  	int eoffset, elen = 0;
  	struct fileIdentDesc *fi;
  	struct fileIdentDesc cfi;
391e8bbd3   Al Viro   sanitize const/si...
821
  	uint8_t *ea;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
822
823
  	int err;
  	int block;
391e8bbd3   Al Viro   sanitize const/si...
824
  	unsigned char *name = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
825
  	int namelen;
48d6d8ff7   Marcin Slusarz   udf: cache struct...
826
  	struct udf_inode_info *iinfo;
d664b6af6   Jan Kara   udf: Move handlin...
827
  	struct super_block *sb = dir->i_sb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
828

a6c5a0342   Dmitry Monakhov   udf: replace inod...
829
  	inode = udf_new_inode(dir, S_IFLNK | S_IRWXUGO, &err);
4b11111ab   Marcin Slusarz   udf: fix coding s...
830
  	if (!inode)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
831
  		goto out;
4d0fb621d   Alessio Igor Bogani   udf: Replace bkl ...
832
833
  	iinfo = UDF_I(inode);
  	down_write(&iinfo->i_data_sem);
b80697c14   Jan Kara   udf: Remove decla...
834
835
836
837
838
  	name = kmalloc(UDF_NAME_LEN, GFP_NOFS);
  	if (!name) {
  		err = -ENOMEM;
  		goto out_no_entry;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
839
  	inode->i_data.a_ops = &udf_symlink_aops;
c15d0fc0f   Dmitry Monakhov   udf: add speciffi...
840
  	inode->i_op = &udf_symlink_inode_operations;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
841

48d6d8ff7   Marcin Slusarz   udf: cache struct...
842
  	if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) {
5ca4e4be8   Pekka Enberg   Remove struct typ...
843
  		struct kernel_lb_addr eloc;
78e917d59   Harvey Harrison   udf: fix sparse w...
844
  		uint32_t bsize;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
845

d664b6af6   Jan Kara   udf: Move handlin...
846
  		block = udf_new_block(sb, inode,
48d6d8ff7   Marcin Slusarz   udf: cache struct...
847
848
  				iinfo->i_location.partitionReferenceNum,
  				iinfo->i_location.logicalBlockNum, &err);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
849
850
  		if (!block)
  			goto out_no_entry;
48d6d8ff7   Marcin Slusarz   udf: cache struct...
851
  		epos.block = iinfo->i_location;
ff116fc8d   Jan Kara   UDF: introduce st...
852
853
  		epos.offset = udf_file_entry_alloc_offset(inode);
  		epos.bh = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
854
  		eloc.logicalBlockNum = block;
4b11111ab   Marcin Slusarz   udf: fix coding s...
855
  		eloc.partitionReferenceNum =
48d6d8ff7   Marcin Slusarz   udf: cache struct...
856
  				iinfo->i_location.partitionReferenceNum;
d664b6af6   Jan Kara   udf: Move handlin...
857
  		bsize = sb->s_blocksize;
78e917d59   Harvey Harrison   udf: fix sparse w...
858
  		iinfo->i_lenExtents = bsize;
97e961fdb   Pekka Enberg   Fix the udf code ...
859
  		udf_add_aext(inode, &epos, &eloc, bsize, 0);
3bf25cb40   Jan Kara   udf: use get_bh()
860
  		brelse(epos.bh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
861

d664b6af6   Jan Kara   udf: Move handlin...
862
  		block = udf_get_pblock(sb, block,
48d6d8ff7   Marcin Slusarz   udf: cache struct...
863
  				iinfo->i_location.partitionReferenceNum,
4b11111ab   Marcin Slusarz   udf: fix coding s...
864
  				0);
d664b6af6   Jan Kara   udf: Move handlin...
865
  		epos.bh = udf_tgetblk(sb, block);
ff116fc8d   Jan Kara   UDF: introduce st...
866
  		lock_buffer(epos.bh);
d664b6af6   Jan Kara   udf: Move handlin...
867
  		memset(epos.bh->b_data, 0x00, bsize);
ff116fc8d   Jan Kara   UDF: introduce st...
868
869
870
871
  		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);
48d6d8ff7   Marcin Slusarz   udf: cache struct...
872
873
  	} else
  		ea = iinfo->i_ext.i_data + iinfo->i_lenEAttr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
874

d664b6af6   Jan Kara   udf: Move handlin...
875
  	eoffset = sb->s_blocksize - udf_ext0_offset(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
876
  	pc = (struct pathComponent *)ea;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
877
878
  	if (*symname == '/') {
  		do {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
879
880
881
882
883
884
  			symname++;
  		} while (*symname == '/');
  
  		pc->componentType = 1;
  		pc->lengthComponentIdent = 0;
  		pc->componentFileVersionNum = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
885
886
887
888
  		elen += sizeof(struct pathComponent);
  	}
  
  	err = -ENAMETOOLONG;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
889
  	while (*symname) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
890
891
892
893
  		if (elen + sizeof(struct pathComponent) > eoffset)
  			goto out_no_entry;
  
  		pc = (struct pathComponent *)(ea + elen);
391e8bbd3   Al Viro   sanitize const/si...
894
  		compstart = symname;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
895

cb00ea352   Cyrill Gorcunov   UDF: coding style...
896
  		do {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
897
898
899
900
901
902
  			symname++;
  		} while (*symname && *symname != '/');
  
  		pc->componentType = 5;
  		pc->lengthComponentIdent = 0;
  		pc->componentFileVersionNum = 0;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
903
904
  		if (compstart[0] == '.') {
  			if ((symname - compstart) == 1)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
905
  				pc->componentType = 4;
4b11111ab   Marcin Slusarz   udf: fix coding s...
906
907
  			else if ((symname - compstart) == 2 &&
  					compstart[1] == '.')
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
908
909
  				pc->componentType = 3;
  		}
cb00ea352   Cyrill Gorcunov   UDF: coding style...
910
  		if (pc->componentType == 5) {
d664b6af6   Jan Kara   udf: Move handlin...
911
  			namelen = udf_put_filename(sb, compstart, name,
28de7948a   Cyrill Gorcunov   UDF: coding style...
912
913
  						   symname - compstart);
  			if (!namelen)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
914
  				goto out_no_entry;
4b11111ab   Marcin Slusarz   udf: fix coding s...
915
916
  			if (elen + sizeof(struct pathComponent) + namelen >
  					eoffset)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
917
918
919
920
921
922
923
924
  				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...
925
926
  		if (*symname) {
  			do {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
927
928
929
930
  				symname++;
  			} while (*symname == '/');
  		}
  	}
3bf25cb40   Jan Kara   udf: use get_bh()
931
  	brelse(epos.bh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
932
  	inode->i_size = elen;
48d6d8ff7   Marcin Slusarz   udf: cache struct...
933
934
  	if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
  		iinfo->i_lenAlloc = inode->i_size;
2c948b3f8   Jan Kara   udf: Avoid IO in ...
935
936
  	else
  		udf_truncate_tail_extent(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
937
  	mark_inode_dirty(inode);
4b11111ab   Marcin Slusarz   udf: fix coding s...
938
939
  	fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err);
  	if (!fi)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
940
  		goto out_no_entry;
d664b6af6   Jan Kara   udf: Move handlin...
941
  	cfi.icb.extLength = cpu_to_le32(sb->s_blocksize);
48d6d8ff7   Marcin Slusarz   udf: cache struct...
942
  	cfi.icb.extLocation = cpu_to_lelb(iinfo->i_location);
d664b6af6   Jan Kara   udf: Move handlin...
943
  	if (UDF_SB(inode->i_sb)->s_lvid_bh) {
28de7948a   Cyrill Gorcunov   UDF: coding style...
944
  		*(__le32 *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse =
d664b6af6   Jan Kara   udf: Move handlin...
945
  			cpu_to_le32(lvid_get_unique_id(sb));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
946
947
  	}
  	udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL);
c0b344385   Marcin Slusarz   udf: remove UDF_I...
948
  	if (UDF_I(dir)->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
949
  		mark_inode_dirty(dir);
4d0fb621d   Alessio Igor Bogani   udf: Replace bkl ...
950
  	up_write(&iinfo->i_data_sem);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
951
  	if (fibh.sbh != fibh.ebh)
3bf25cb40   Jan Kara   udf: use get_bh()
952
953
  		brelse(fibh.ebh);
  	brelse(fibh.sbh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
954
955
  	d_instantiate(dentry, inode);
  	err = 0;
28de7948a   Cyrill Gorcunov   UDF: coding style...
956
  out:
b80697c14   Jan Kara   udf: Remove decla...
957
  	kfree(name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
958
  	return err;
28de7948a   Cyrill Gorcunov   UDF: coding style...
959
  out_no_entry:
4d0fb621d   Alessio Igor Bogani   udf: Replace bkl ...
960
  	up_write(&iinfo->i_data_sem);
9a53c3a78   Dave Hansen   [PATCH] r/o bind ...
961
  	inode_dec_link_count(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
962
963
964
  	iput(inode);
  	goto out;
  }
cb00ea352   Cyrill Gorcunov   UDF: coding style...
965
966
  static int udf_link(struct dentry *old_dentry, struct inode *dir,
  		    struct dentry *dentry)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
967
968
969
970
971
  {
  	struct inode *inode = old_dentry->d_inode;
  	struct udf_fileident_bh fibh;
  	struct fileIdentDesc cfi, *fi;
  	int err;
810c1b2e4   Al Viro   udf: fix i_nlink ...
972
  	if (inode->i_nlink >= UDF_MAX_LINKS)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
973
  		return -EMLINK;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
974

4b11111ab   Marcin Slusarz   udf: fix coding s...
975
976
  	fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err);
  	if (!fi) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
977
978
979
  		return err;
  	}
  	cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
c0b344385   Marcin Slusarz   udf: remove UDF_I...
980
  	cfi.icb.extLocation = cpu_to_lelb(UDF_I(inode)->i_location);
d664b6af6   Jan Kara   udf: Move handlin...
981
  	if (UDF_SB(inode->i_sb)->s_lvid_bh) {
28de7948a   Cyrill Gorcunov   UDF: coding style...
982
  		*(__le32 *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse =
d664b6af6   Jan Kara   udf: Move handlin...
983
  			cpu_to_le32(lvid_get_unique_id(inode->i_sb));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
984
985
  	}
  	udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL);
c0b344385   Marcin Slusarz   udf: remove UDF_I...
986
  	if (UDF_I(dir)->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
987
  		mark_inode_dirty(dir);
28de7948a   Cyrill Gorcunov   UDF: coding style...
988

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
989
  	if (fibh.sbh != fibh.ebh)
3bf25cb40   Jan Kara   udf: use get_bh()
990
991
  		brelse(fibh.ebh);
  	brelse(fibh.sbh);
d8c76e6f4   Dave Hansen   [PATCH] r/o bind ...
992
  	inc_nlink(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
993
994
  	inode->i_ctime = current_fs_time(inode->i_sb);
  	mark_inode_dirty(inode);
7de9c6ee3   Al Viro   new helper: ihold()
995
  	ihold(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
996
  	d_instantiate(dentry, inode);
28de7948a   Cyrill Gorcunov   UDF: coding style...
997

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
998
999
1000
1001
1002
1003
  	return 0;
  }
  
  /* Anybody can rename anything with this: the permission checks are left to the
   * higher-level routines.
   */
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1004
1005
  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
1006
  {
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1007
1008
  	struct inode *old_inode = old_dentry->d_inode;
  	struct inode *new_inode = new_dentry->d_inode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1009
  	struct udf_fileident_bh ofibh, nfibh;
4b11111ab   Marcin Slusarz   udf: fix coding s...
1010
1011
  	struct fileIdentDesc *ofi = NULL, *nfi = NULL, *dir_fi = NULL;
  	struct fileIdentDesc ocfi, ncfi;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1012
1013
  	struct buffer_head *dir_bh = NULL;
  	int retval = -ENOENT;
5ca4e4be8   Pekka Enberg   Remove struct typ...
1014
  	struct kernel_lb_addr tloc;
48d6d8ff7   Marcin Slusarz   udf: cache struct...
1015
  	struct udf_inode_info *old_iinfo = UDF_I(old_inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1016

9fbb76ce0   Al Viro   [PATCH] get rid o...
1017
  	ofi = udf_find_entry(old_dir, &old_dentry->d_name, &ofibh, &ocfi);
4b11111ab   Marcin Slusarz   udf: fix coding s...
1018
  	if (ofi) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1019
  		if (ofibh.sbh != ofibh.ebh)
3bf25cb40   Jan Kara   udf: use get_bh()
1020
1021
  			brelse(ofibh.ebh);
  		brelse(ofibh.sbh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1022
1023
  	}
  	tloc = lelb_to_cpu(ocfi.icb.extLocation);
97e961fdb   Pekka Enberg   Fix the udf code ...
1024
  	if (!ofi || udf_get_lb_pblock(old_dir->i_sb, &tloc, 0)
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1025
  	    != old_inode->i_ino)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1026
  		goto end_rename;
9fbb76ce0   Al Viro   [PATCH] get rid o...
1027
  	nfi = udf_find_entry(new_dir, &new_dentry->d_name, &nfibh, &ncfi);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1028
1029
  	if (nfi) {
  		if (!new_inode) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1030
  			if (nfibh.sbh != nfibh.ebh)
3bf25cb40   Jan Kara   udf: use get_bh()
1031
1032
  				brelse(nfibh.ebh);
  			brelse(nfibh.sbh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1033
1034
1035
  			nfi = NULL;
  		}
  	}
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1036
  	if (S_ISDIR(old_inode->i_mode)) {
7f3fbd089   Marcin Slusarz   udf: fix signedne...
1037
  		int offset = udf_ext0_offset(old_inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1038

cb00ea352   Cyrill Gorcunov   UDF: coding style...
1039
  		if (new_inode) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1040
1041
1042
1043
1044
  			retval = -ENOTEMPTY;
  			if (!empty_dir(new_inode))
  				goto end_rename;
  		}
  		retval = -EIO;
48d6d8ff7   Marcin Slusarz   udf: cache struct...
1045
  		if (old_iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
4b11111ab   Marcin Slusarz   udf: fix coding s...
1046
  			dir_fi = udf_get_fileident(
48d6d8ff7   Marcin Slusarz   udf: cache struct...
1047
1048
  					old_iinfo->i_ext.i_data -
  					  (old_iinfo->i_efe ?
4b11111ab   Marcin Slusarz   udf: fix coding s...
1049
1050
1051
  					   sizeof(struct extendedFileEntry) :
  					   sizeof(struct fileEntry)),
  					old_inode->i_sb->s_blocksize, &offset);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1052
  		} else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1053
1054
1055
  			dir_bh = udf_bread(old_inode, 0, 0, &retval);
  			if (!dir_bh)
  				goto end_rename;
4b11111ab   Marcin Slusarz   udf: fix coding s...
1056
1057
  			dir_fi = udf_get_fileident(dir_bh->b_data,
  					old_inode->i_sb->s_blocksize, &offset);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1058
1059
1060
1061
  		}
  		if (!dir_fi)
  			goto end_rename;
  		tloc = lelb_to_cpu(dir_fi->icb.extLocation);
97e961fdb   Pekka Enberg   Fix the udf code ...
1062
  		if (udf_get_lb_pblock(old_inode->i_sb, &tloc, 0) !=
4b11111ab   Marcin Slusarz   udf: fix coding s...
1063
  				old_dir->i_ino)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1064
1065
1066
  			goto end_rename;
  
  		retval = -EMLINK;
810c1b2e4   Al Viro   udf: fix i_nlink ...
1067
  		if (!new_inode && new_dir->i_nlink >= UDF_MAX_LINKS)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1068
1069
  			goto end_rename;
  	}
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1070
  	if (!nfi) {
4b11111ab   Marcin Slusarz   udf: fix coding s...
1071
1072
  		nfi = udf_add_entry(new_dir, new_dentry, &nfibh, &ncfi,
  				    &retval);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
  		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;
5ca4e4be8   Pekka Enberg   Remove struct typ...
1089
  	memcpy(&(ncfi.icb), &(ocfi.icb), sizeof(struct long_ad));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1090
1091
1092
  	udf_write_fi(new_dir, &ncfi, nfi, &nfibh, NULL, NULL);
  
  	/* The old fid may have moved - find it again */
9fbb76ce0   Al Viro   [PATCH] get rid o...
1093
  	ofi = udf_find_entry(old_dir, &old_dentry->d_name, &ofibh, &ocfi);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1094
  	udf_delete_entry(old_dir, ofi, &ofibh, &ocfi);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1095
  	if (new_inode) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1096
  		new_inode->i_ctime = current_fs_time(new_inode->i_sb);
9a53c3a78   Dave Hansen   [PATCH] r/o bind ...
1097
  		inode_dec_link_count(new_inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1098
1099
1100
  	}
  	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...
1101
  	if (dir_fi) {
c0b344385   Marcin Slusarz   udf: remove UDF_I...
1102
  		dir_fi->icb.extLocation = cpu_to_lelb(UDF_I(new_dir)->i_location);
4b11111ab   Marcin Slusarz   udf: fix coding s...
1103
1104
1105
  		udf_update_tag((char *)dir_fi,
  				(sizeof(struct fileIdentDesc) +
  				le16_to_cpu(dir_fi->lengthOfImpUse) + 3) & ~3);
48d6d8ff7   Marcin Slusarz   udf: cache struct...
1106
  		if (old_iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1107
  			mark_inode_dirty(old_inode);
4b11111ab   Marcin Slusarz   udf: fix coding s...
1108
  		else
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1109
  			mark_buffer_dirty_inode(dir_bh, old_inode);
4b11111ab   Marcin Slusarz   udf: fix coding s...
1110

9a53c3a78   Dave Hansen   [PATCH] r/o bind ...
1111
  		inode_dec_link_count(old_dir);
4b11111ab   Marcin Slusarz   udf: fix coding s...
1112
  		if (new_inode)
9a53c3a78   Dave Hansen   [PATCH] r/o bind ...
1113
  			inode_dec_link_count(new_inode);
4b11111ab   Marcin Slusarz   udf: fix coding s...
1114
  		else {
d8c76e6f4   Dave Hansen   [PATCH] r/o bind ...
1115
  			inc_nlink(new_dir);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1116
1117
1118
  			mark_inode_dirty(new_dir);
  		}
  	}
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1119
  	if (ofi) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1120
  		if (ofibh.sbh != ofibh.ebh)
3bf25cb40   Jan Kara   udf: use get_bh()
1121
1122
  			brelse(ofibh.ebh);
  		brelse(ofibh.sbh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1123
1124
1125
  	}
  
  	retval = 0;
28de7948a   Cyrill Gorcunov   UDF: coding style...
1126
  end_rename:
3bf25cb40   Jan Kara   udf: use get_bh()
1127
  	brelse(dir_bh);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1128
  	if (nfi) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1129
  		if (nfibh.sbh != nfibh.ebh)
3bf25cb40   Jan Kara   udf: use get_bh()
1130
1131
  			brelse(nfibh.ebh);
  		brelse(nfibh.sbh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1132
  	}
28de7948a   Cyrill Gorcunov   UDF: coding style...
1133

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1134
1135
  	return retval;
  }
221e583a7   Rasmus Rohde   udf: Make udf exp...
1136
1137
  static struct dentry *udf_get_parent(struct dentry *child)
  {
97e961fdb   Pekka Enberg   Fix the udf code ...
1138
  	struct kernel_lb_addr tloc;
221e583a7   Rasmus Rohde   udf: Make udf exp...
1139
  	struct inode *inode = NULL;
9fbb76ce0   Al Viro   [PATCH] get rid o...
1140
  	struct qstr dotdot = {.name = "..", .len = 2};
221e583a7   Rasmus Rohde   udf: Make udf exp...
1141
1142
  	struct fileIdentDesc cfi;
  	struct udf_fileident_bh fibh;
221e583a7   Rasmus Rohde   udf: Make udf exp...
1143
1144
1145
1146
1147
1148
  	if (!udf_find_entry(child->d_inode, &dotdot, &fibh, &cfi))
  		goto out_unlock;
  
  	if (fibh.sbh != fibh.ebh)
  		brelse(fibh.ebh);
  	brelse(fibh.sbh);
97e961fdb   Pekka Enberg   Fix the udf code ...
1149
1150
  	tloc = lelb_to_cpu(cfi.icb.extLocation);
  	inode = udf_iget(child->d_inode->i_sb, &tloc);
221e583a7   Rasmus Rohde   udf: Make udf exp...
1151
1152
  	if (!inode)
  		goto out_unlock;
221e583a7   Rasmus Rohde   udf: Make udf exp...
1153

440037287   Christoph Hellwig   [PATCH] switch al...
1154
  	return d_obtain_alias(inode);
221e583a7   Rasmus Rohde   udf: Make udf exp...
1155
  out_unlock:
221e583a7   Rasmus Rohde   udf: Make udf exp...
1156
1157
1158
1159
1160
1161
1162
1163
  	return ERR_PTR(-EACCES);
  }
  
  
  static struct dentry *udf_nfs_get_inode(struct super_block *sb, u32 block,
  					u16 partref, __u32 generation)
  {
  	struct inode *inode;
5ca4e4be8   Pekka Enberg   Remove struct typ...
1164
  	struct kernel_lb_addr loc;
221e583a7   Rasmus Rohde   udf: Make udf exp...
1165
1166
1167
1168
1169
1170
  
  	if (block == 0)
  		return ERR_PTR(-ESTALE);
  
  	loc.logicalBlockNum = block;
  	loc.partitionReferenceNum = partref;
97e961fdb   Pekka Enberg   Fix the udf code ...
1171
  	inode = udf_iget(sb, &loc);
221e583a7   Rasmus Rohde   udf: Make udf exp...
1172
1173
1174
1175
1176
1177
1178
1179
  
  	if (inode == NULL)
  		return ERR_PTR(-ENOMEM);
  
  	if (generation && inode->i_generation != generation) {
  		iput(inode);
  		return ERR_PTR(-ESTALE);
  	}
440037287   Christoph Hellwig   [PATCH] switch al...
1180
  	return d_obtain_alias(inode);
221e583a7   Rasmus Rohde   udf: Make udf exp...
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
  }
  
  static struct dentry *udf_fh_to_dentry(struct super_block *sb,
  				       struct fid *fid, int fh_len, int fh_type)
  {
  	if ((fh_len != 3 && fh_len != 5) ||
  	    (fh_type != FILEID_UDF_WITH_PARENT &&
  	     fh_type != FILEID_UDF_WITHOUT_PARENT))
  		return NULL;
  
  	return udf_nfs_get_inode(sb, fid->udf.block, fid->udf.partref,
  			fid->udf.generation);
  }
  
  static struct dentry *udf_fh_to_parent(struct super_block *sb,
  				       struct fid *fid, int fh_len, int fh_type)
  {
  	if (fh_len != 5 || fh_type != FILEID_UDF_WITH_PARENT)
  		return NULL;
  
  	return udf_nfs_get_inode(sb, fid->udf.parent_block,
  				 fid->udf.parent_partref,
  				 fid->udf.parent_generation);
  }
  static int udf_encode_fh(struct dentry *de, __u32 *fh, int *lenp,
  			 int connectable)
  {
  	int len = *lenp;
  	struct inode *inode =  de->d_inode;
5ca4e4be8   Pekka Enberg   Remove struct typ...
1210
  	struct kernel_lb_addr location = UDF_I(inode)->i_location;
221e583a7   Rasmus Rohde   udf: Make udf exp...
1211
1212
  	struct fid *fid = (struct fid *)fh;
  	int type = FILEID_UDF_WITHOUT_PARENT;
5fe0c2378   Aneesh Kumar K.V   exportfs: Return ...
1213
1214
  	if (connectable && (len < 5)) {
  		*lenp = 5;
221e583a7   Rasmus Rohde   udf: Make udf exp...
1215
  		return 255;
5fe0c2378   Aneesh Kumar K.V   exportfs: Return ...
1216
1217
1218
1219
  	} else if (len < 3) {
  		*lenp = 3;
  		return 255;
  	}
221e583a7   Rasmus Rohde   udf: Make udf exp...
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
  
  	*lenp = 3;
  	fid->udf.block = location.logicalBlockNum;
  	fid->udf.partref = location.partitionReferenceNum;
  	fid->udf.generation = inode->i_generation;
  
  	if (connectable && !S_ISDIR(inode->i_mode)) {
  		spin_lock(&de->d_lock);
  		inode = de->d_parent->d_inode;
  		location = UDF_I(inode)->i_location;
  		fid->udf.parent_block = location.logicalBlockNum;
  		fid->udf.parent_partref = location.partitionReferenceNum;
  		fid->udf.parent_generation = inode->i_generation;
  		spin_unlock(&de->d_lock);
  		*lenp = 5;
  		type = FILEID_UDF_WITH_PARENT;
  	}
  
  	return type;
  }
  
  const struct export_operations udf_export_ops = {
  	.encode_fh	= udf_encode_fh,
  	.fh_to_dentry   = udf_fh_to_dentry,
  	.fh_to_parent   = udf_fh_to_parent,
  	.get_parent     = udf_get_parent,
  };
c5ef1c42c   Arjan van de Ven   [PATCH] mark stru...
1247
  const struct inode_operations udf_dir_inode_operations = {
28de7948a   Cyrill Gorcunov   UDF: coding style...
1248
1249
1250
1251
1252
1253
1254
1255
1256
  	.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
1257
  };
c15d0fc0f   Dmitry Monakhov   udf: add speciffi...
1258
1259
1260
1261
  const struct inode_operations udf_symlink_inode_operations = {
  	.readlink	= generic_readlink,
  	.follow_link	= page_follow_link_light,
  	.put_link	= page_put_link,
c15d0fc0f   Dmitry Monakhov   udf: add speciffi...
1262
  };