xref: /openbmc/linux/fs/udf/namei.c (revision 59ad88f2)
15ce34554SBagas Sanjaya // SPDX-License-Identifier: GPL-2.0-only
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds  * namei.c
41da177e4SLinus Torvalds  *
51da177e4SLinus Torvalds  * PURPOSE
61da177e4SLinus Torvalds  *      Inode name handling routines for the OSTA-UDF(tm) filesystem.
71da177e4SLinus Torvalds  *
81da177e4SLinus Torvalds  * COPYRIGHT
91da177e4SLinus Torvalds  *  (C) 1998-2004 Ben Fennema
101da177e4SLinus Torvalds  *  (C) 1999-2000 Stelias Computing Inc
111da177e4SLinus Torvalds  *
121da177e4SLinus Torvalds  * HISTORY
131da177e4SLinus Torvalds  *
141da177e4SLinus Torvalds  *  12/12/98 blf  Created. Split out the lookup code from dir.c
151da177e4SLinus Torvalds  *  04/19/99 blf  link, mknod, symlink support
161da177e4SLinus Torvalds  */
171da177e4SLinus Torvalds 
181da177e4SLinus Torvalds #include "udfdecl.h"
191da177e4SLinus Torvalds 
201da177e4SLinus Torvalds #include "udf_i.h"
211da177e4SLinus Torvalds #include "udf_sb.h"
221da177e4SLinus Torvalds #include <linux/string.h>
231da177e4SLinus Torvalds #include <linux/errno.h>
241da177e4SLinus Torvalds #include <linux/mm.h>
251da177e4SLinus Torvalds #include <linux/slab.h>
26e8edc6e0SAlexey Dobriyan #include <linux/sched.h>
27f845fcedSBob Copeland #include <linux/crc-itu-t.h>
28221e583aSRasmus Rohde #include <linux/exportfs.h>
29a48fc69fSJan Kara #include <linux/iversion.h>
301da177e4SLinus Torvalds 
udf_match(int len1,const unsigned char * name1,int len2,const unsigned char * name2)31391e8bbdSAl Viro static inline int udf_match(int len1, const unsigned char *name1, int len2,
32391e8bbdSAl Viro 			    const unsigned char *name2)
331da177e4SLinus Torvalds {
341da177e4SLinus Torvalds 	if (len1 != len2)
351da177e4SLinus Torvalds 		return 0;
3628de7948SCyrill Gorcunov 
371da177e4SLinus Torvalds 	return !memcmp(name1, name2, len1);
381da177e4SLinus Torvalds }
391da177e4SLinus Torvalds 
40231473f6SFabian Frederick /**
411c80afa0SJan Kara  * udf_fiiter_find_entry - find entry in given directory.
42231473f6SFabian Frederick  *
43231473f6SFabian Frederick  * @dir:	directory inode to search in
44231473f6SFabian Frederick  * @child:	qstr of the name
451c80afa0SJan Kara  * @iter:	iter to use for searching
46231473f6SFabian Frederick  *
47231473f6SFabian Frederick  * This function searches in the directory @dir for a file name @child. When
481c80afa0SJan Kara  * found, @iter points to the position in the directory with given entry.
49231473f6SFabian Frederick  *
501c80afa0SJan Kara  * Returns 0 on success, < 0 on error (including -ENOENT).
51231473f6SFabian Frederick  */
udf_fiiter_find_entry(struct inode * dir,const struct qstr * child,struct udf_fileident_iter * iter)521c80afa0SJan Kara static int udf_fiiter_find_entry(struct inode *dir, const struct qstr *child,
531c80afa0SJan Kara 				 struct udf_fileident_iter *iter)
541da177e4SLinus Torvalds {
55b490bdd6SSteve Magnani 	int flen;
561c80afa0SJan Kara 	unsigned char *fname = NULL;
571c80afa0SJan Kara 	struct super_block *sb = dir->i_sb;
589fbb76ceSAl Viro 	int isdotdot = child->len == 2 &&
599fbb76ceSAl Viro 		child->name[0] == '.' && child->name[1] == '.';
601c80afa0SJan Kara 	int ret;
61b80697c1SJan Kara 
62b80697c1SJan Kara 	fname = kmalloc(UDF_NAME_LEN, GFP_NOFS);
631c80afa0SJan Kara 	if (!fname)
641c80afa0SJan Kara 		return -ENOMEM;
651da177e4SLinus Torvalds 
661c80afa0SJan Kara 	for (ret = udf_fiiter_init(iter, dir, 0);
671c80afa0SJan Kara 	     !ret && iter->pos < dir->i_size;
681c80afa0SJan Kara 	     ret = udf_fiiter_advance(iter)) {
691c80afa0SJan Kara 		if (iter->fi.fileCharacteristics & FID_FILE_CHAR_DELETED) {
703ee3039cSJan Kara 			if (!UDF_QUERY_FLAG(sb, UDF_FLAG_UNDELETE))
711da177e4SLinus Torvalds 				continue;
721da177e4SLinus Torvalds 		}
731da177e4SLinus Torvalds 
741c80afa0SJan Kara 		if (iter->fi.fileCharacteristics & FID_FILE_CHAR_HIDDEN) {
753ee3039cSJan Kara 			if (!UDF_QUERY_FLAG(sb, UDF_FLAG_UNHIDE))
761da177e4SLinus Torvalds 				continue;
771da177e4SLinus Torvalds 		}
781da177e4SLinus Torvalds 
791c80afa0SJan Kara 		if ((iter->fi.fileCharacteristics & FID_FILE_CHAR_PARENT) &&
80a4264b3fSJesper Juhl 		    isdotdot)
81a4264b3fSJesper Juhl 			goto out_ok;
82221e583aSRasmus Rohde 
831c80afa0SJan Kara 		if (!iter->fi.lengthFileIdent)
841da177e4SLinus Torvalds 			continue;
851da177e4SLinus Torvalds 
861c80afa0SJan Kara 		flen = udf_get_filename(sb, iter->name,
871c80afa0SJan Kara 				iter->fi.lengthFileIdent, fname, UDF_NAME_LEN);
88231473f6SFabian Frederick 		if (flen < 0) {
891c80afa0SJan Kara 			ret = flen;
90231473f6SFabian Frederick 			goto out_err;
91231473f6SFabian Frederick 		}
92231473f6SFabian Frederick 
93231473f6SFabian Frederick 		if (udf_match(flen, fname, child->len, child->name))
94b80697c1SJan Kara 			goto out_ok;
951da177e4SLinus Torvalds 	}
961c80afa0SJan Kara 	if (!ret)
971c80afa0SJan Kara 		ret = -ENOENT;
9828de7948SCyrill Gorcunov 
99231473f6SFabian Frederick out_err:
1001c80afa0SJan Kara 	udf_fiiter_release(iter);
101b80697c1SJan Kara out_ok:
102b80697c1SJan Kara 	kfree(fname);
10328de7948SCyrill Gorcunov 
1041c80afa0SJan Kara 	return ret;
1051da177e4SLinus Torvalds }
1061da177e4SLinus Torvalds 
udf_lookup(struct inode * dir,struct dentry * dentry,unsigned int flags)107cb00ea35SCyrill Gorcunov static struct dentry *udf_lookup(struct inode *dir, struct dentry *dentry,
10800cd8dd3SAl Viro 				 unsigned int flags)
1091da177e4SLinus Torvalds {
1101da177e4SLinus Torvalds 	struct inode *inode = NULL;
111200918b3SJan Kara 	struct udf_fileident_iter iter;
112200918b3SJan Kara 	int err;
1131da177e4SLinus Torvalds 
1149fba7056SAndrew Gabbasov 	if (dentry->d_name.len > UDF_NAME_LEN)
1151da177e4SLinus Torvalds 		return ERR_PTR(-ENAMETOOLONG);
1161da177e4SLinus Torvalds 
117200918b3SJan Kara 	err = udf_fiiter_find_entry(dir, &dentry->d_name, &iter);
118200918b3SJan Kara 	if (err < 0 && err != -ENOENT)
119200918b3SJan Kara 		return ERR_PTR(err);
120231473f6SFabian Frederick 
121200918b3SJan Kara 	if (err == 0) {
12297e961fdSPekka Enberg 		struct kernel_lb_addr loc;
12397e961fdSPekka Enberg 
124200918b3SJan Kara 		loc = lelb_to_cpu(iter.fi.icb.extLocation);
125200918b3SJan Kara 		udf_fiiter_release(&iter);
1261da177e4SLinus Torvalds 
12797e961fdSPekka Enberg 		inode = udf_iget(dir->i_sb, &loc);
1286d3d5e86SJan Kara 		if (IS_ERR(inode))
1296d3d5e86SJan Kara 			return ERR_CAST(inode);
1301da177e4SLinus Torvalds 	}
13128de7948SCyrill Gorcunov 
132221e583aSRasmus Rohde 	return d_splice_alias(inode, dentry);
1331da177e4SLinus Torvalds }
1341da177e4SLinus Torvalds 
udf_expand_dir_adinicb(struct inode * inode,udf_pblk_t * block)135f386c802SJan Kara static int udf_expand_dir_adinicb(struct inode *inode, udf_pblk_t *block)
1361da177e4SLinus Torvalds {
137a27b2923SJan Kara 	udf_pblk_t newblock;
138a27b2923SJan Kara 	struct buffer_head *dbh = NULL;
1395ca4e4beSPekka Enberg 	struct kernel_lb_addr eloc;
140a27b2923SJan Kara 	struct extent_position epos;
141a27b2923SJan Kara 	uint8_t alloctype;
142a27b2923SJan Kara 	struct udf_inode_info *iinfo = UDF_I(inode);
143a27b2923SJan Kara 	struct udf_fileident_iter iter;
144a27b2923SJan Kara 	uint8_t *impuse;
145a27b2923SJan Kara 	int ret;
1461da177e4SLinus Torvalds 
147a27b2923SJan Kara 	if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
148a27b2923SJan Kara 		alloctype = ICBTAG_FLAG_AD_SHORT;
149a27b2923SJan Kara 	else
150a27b2923SJan Kara 		alloctype = ICBTAG_FLAG_AD_LONG;
151a27b2923SJan Kara 
152a27b2923SJan Kara 	if (!inode->i_size) {
153a27b2923SJan Kara 		iinfo->i_alloc_type = alloctype;
154a27b2923SJan Kara 		mark_inode_dirty(inode);
155f386c802SJan Kara 		return 0;
156b80697c1SJan Kara 	}
157b80697c1SJan Kara 
158a27b2923SJan Kara 	/* alloc block, and copy data to it */
159a27b2923SJan Kara 	*block = udf_new_block(inode->i_sb, inode,
160a27b2923SJan Kara 			       iinfo->i_location.partitionReferenceNum,
161f386c802SJan Kara 			       iinfo->i_location.logicalBlockNum, &ret);
162a27b2923SJan Kara 	if (!(*block))
163f386c802SJan Kara 		return ret;
164a27b2923SJan Kara 	newblock = udf_get_pblock(inode->i_sb, *block,
165a27b2923SJan Kara 				  iinfo->i_location.partitionReferenceNum,
166a27b2923SJan Kara 				0);
167f386c802SJan Kara 	if (newblock == 0xffffffff)
168f386c802SJan Kara 		return -EFSCORRUPTED;
169101ee137SJan Kara 	dbh = sb_getblk(inode->i_sb, newblock);
170a27b2923SJan Kara 	if (!dbh)
171f386c802SJan Kara 		return -ENOMEM;
172a27b2923SJan Kara 	lock_buffer(dbh);
173a27b2923SJan Kara 	memcpy(dbh->b_data, iinfo->i_data, inode->i_size);
174a27b2923SJan Kara 	memset(dbh->b_data + inode->i_size, 0,
175a27b2923SJan Kara 	       inode->i_sb->s_blocksize - inode->i_size);
176a27b2923SJan Kara 	set_buffer_uptodate(dbh);
177a27b2923SJan Kara 	unlock_buffer(dbh);
178a27b2923SJan Kara 
179a27b2923SJan Kara 	/* Drop inline data, add block instead */
180a27b2923SJan Kara 	iinfo->i_alloc_type = alloctype;
181a27b2923SJan Kara 	memset(iinfo->i_data + iinfo->i_lenEAttr, 0, iinfo->i_lenAlloc);
182a27b2923SJan Kara 	iinfo->i_lenAlloc = 0;
183a27b2923SJan Kara 	eloc.logicalBlockNum = *block;
184a27b2923SJan Kara 	eloc.partitionReferenceNum =
185a27b2923SJan Kara 				iinfo->i_location.partitionReferenceNum;
186a27b2923SJan Kara 	iinfo->i_lenExtents = inode->i_size;
187a27b2923SJan Kara 	epos.bh = NULL;
188a27b2923SJan Kara 	epos.block = iinfo->i_location;
189a27b2923SJan Kara 	epos.offset = udf_file_entry_alloc_offset(inode);
19033e9a53cSJan Kara 	ret = udf_add_aext(inode, &epos, &eloc, inode->i_size, 0);
191a27b2923SJan Kara 	brelse(epos.bh);
19233e9a53cSJan Kara 	if (ret < 0) {
193f386c802SJan Kara 		brelse(dbh);
19433e9a53cSJan Kara 		udf_free_blocks(inode->i_sb, inode, &eloc, 0, 1);
195f386c802SJan Kara 		return ret;
19633e9a53cSJan Kara 	}
197a27b2923SJan Kara 	mark_inode_dirty(inode);
198a27b2923SJan Kara 
199a27b2923SJan Kara 	/* Now fixup tags in moved directory entries */
200a27b2923SJan Kara 	for (ret = udf_fiiter_init(&iter, inode, 0);
201a27b2923SJan Kara 	     !ret && iter.pos < inode->i_size;
202a27b2923SJan Kara 	     ret = udf_fiiter_advance(&iter)) {
203a27b2923SJan Kara 		iter.fi.descTag.tagLocation = cpu_to_le32(*block);
204a27b2923SJan Kara 		if (iter.fi.lengthOfImpUse != cpu_to_le16(0))
205a27b2923SJan Kara 			impuse = dbh->b_data + iter.pos +
206a27b2923SJan Kara 						sizeof(struct fileIdentDesc);
207a27b2923SJan Kara 		else
208a27b2923SJan Kara 			impuse = NULL;
209a27b2923SJan Kara 		udf_fiiter_write_fi(&iter, impuse);
210a27b2923SJan Kara 	}
211f386c802SJan Kara 	brelse(dbh);
212a27b2923SJan Kara 	/*
213a27b2923SJan Kara 	 * We don't expect the iteration to fail as the directory has been
214a27b2923SJan Kara 	 * already verified to be correct
215a27b2923SJan Kara 	 */
216a27b2923SJan Kara 	WARN_ON_ONCE(ret);
217a27b2923SJan Kara 	udf_fiiter_release(&iter);
218a27b2923SJan Kara 
219f386c802SJan Kara 	return 0;
220a27b2923SJan Kara }
221a27b2923SJan Kara 
udf_fiiter_add_entry(struct inode * dir,struct dentry * dentry,struct udf_fileident_iter * iter)222f2844803SJan Kara static int udf_fiiter_add_entry(struct inode *dir, struct dentry *dentry,
223f2844803SJan Kara 				struct udf_fileident_iter *iter)
224f2844803SJan Kara {
225f2844803SJan Kara 	struct udf_inode_info *dinfo = UDF_I(dir);
226f2844803SJan Kara 	int nfidlen, namelen = 0;
227f2844803SJan Kara 	int ret;
228f2844803SJan Kara 	int off, blksize = 1 << dir->i_blkbits;
229f2844803SJan Kara 	udf_pblk_t block;
230f2844803SJan Kara 	char name[UDF_NAME_LEN_CS0];
231f2844803SJan Kara 
232cb00ea35SCyrill Gorcunov 	if (dentry) {
233f2844803SJan Kara 		if (!dentry->d_name.len)
234f2844803SJan Kara 			return -EINVAL;
235f2844803SJan Kara 		namelen = udf_put_filename(dir->i_sb, dentry->d_name.name,
236525e2c56SAndrew Gabbasov 					   dentry->d_name.len,
2379fba7056SAndrew Gabbasov 					   name, UDF_NAME_LEN_CS0);
238f2844803SJan Kara 		if (!namelen)
239f2844803SJan Kara 			return -ENAMETOOLONG;
2401da177e4SLinus Torvalds 	}
241f2e83347SJan Kara 	nfidlen = ALIGN(sizeof(struct fileIdentDesc) + namelen, UDF_NAME_PAD);
2421da177e4SLinus Torvalds 
243f2844803SJan Kara 	for (ret = udf_fiiter_init(iter, dir, 0);
244f2844803SJan Kara 	     !ret && iter->pos < dir->i_size;
245f2844803SJan Kara 	     ret = udf_fiiter_advance(iter)) {
246f2844803SJan Kara 		if (iter->fi.fileCharacteristics & FID_FILE_CHAR_DELETED) {
247f2844803SJan Kara 			if (udf_dir_entry_len(&iter->fi) == nfidlen) {
248f2844803SJan Kara 				iter->fi.descTag.tagSerialNum = cpu_to_le16(1);
249f2844803SJan Kara 				iter->fi.fileVersionNum = cpu_to_le16(1);
250f2844803SJan Kara 				iter->fi.fileCharacteristics = 0;
251f2844803SJan Kara 				iter->fi.lengthFileIdent = namelen;
252f2844803SJan Kara 				iter->fi.lengthOfImpUse = cpu_to_le16(0);
253f2844803SJan Kara 				memcpy(iter->namebuf, name, namelen);
254f2844803SJan Kara 				iter->name = iter->namebuf;
255f2844803SJan Kara 				return 0;
2561da177e4SLinus Torvalds 			}
2571da177e4SLinus Torvalds 		}
2581da177e4SLinus Torvalds 	}
259f2844803SJan Kara 	if (ret) {
260f2844803SJan Kara 		udf_fiiter_release(iter);
261f2844803SJan Kara 		return ret;
2621da177e4SLinus Torvalds 	}
26348d6d8ffSMarcin Slusarz 	if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB &&
264f2844803SJan Kara 	    blksize - udf_ext0_offset(dir) - iter->pos < nfidlen) {
265f2844803SJan Kara 		udf_fiiter_release(iter);
266f386c802SJan Kara 		ret = udf_expand_dir_adinicb(dir, &block);
267f386c802SJan Kara 		if (ret)
268f2844803SJan Kara 			return ret;
269f2844803SJan Kara 		ret = udf_fiiter_init(iter, dir, dir->i_size);
270f2844803SJan Kara 		if (ret < 0)
271f2844803SJan Kara 			return ret;
2721da177e4SLinus Torvalds 	}
2731da177e4SLinus Torvalds 
274f2844803SJan Kara 	/* Get blocknumber to use for entry tag */
27548d6d8ffSMarcin Slusarz 	if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
27648d6d8ffSMarcin Slusarz 		block = dinfo->i_location.logicalBlockNum;
277cb00ea35SCyrill Gorcunov 	} else {
278f2844803SJan Kara 		block = iter->eloc.logicalBlockNum +
279f2844803SJan Kara 				((iter->elen - 1) >> dir->i_blkbits);
2801da177e4SLinus Torvalds 	}
281f2844803SJan Kara 	off = iter->pos & (blksize - 1);
282f2844803SJan Kara 	if (!off)
283f2844803SJan Kara 		off = blksize;
284f2844803SJan Kara 	/* Entry fits into current block? */
285f2844803SJan Kara 	if (blksize - udf_ext0_offset(dir) - off >= nfidlen)
286f2844803SJan Kara 		goto store_fi;
2872c948b3fSJan Kara 
288f2844803SJan Kara 	ret = udf_fiiter_append_blk(iter);
289f2844803SJan Kara 	if (ret) {
290f2844803SJan Kara 		udf_fiiter_release(iter);
291f2844803SJan Kara 		return ret;
2921da177e4SLinus Torvalds 	}
2931da177e4SLinus Torvalds 
294f2844803SJan Kara 	/* Entry will be completely in the new block? Update tag location... */
295f2844803SJan Kara 	if (!(iter->pos & (blksize - 1)))
296f2844803SJan Kara 		block = iter->eloc.logicalBlockNum +
297f2844803SJan Kara 				((iter->elen - 1) >> dir->i_blkbits);
298f2844803SJan Kara store_fi:
299f2844803SJan Kara 	memset(&iter->fi, 0, sizeof(struct fileIdentDesc));
300f2844803SJan Kara 	if (UDF_SB(dir->i_sb)->s_udfrev >= 0x0200)
301f2844803SJan Kara 		udf_new_tag((char *)(&iter->fi), TAG_IDENT_FID, 3, 1, block,
3025ca4e4beSPekka Enberg 			    sizeof(struct tag));
3031da177e4SLinus Torvalds 	else
304f2844803SJan Kara 		udf_new_tag((char *)(&iter->fi), TAG_IDENT_FID, 2, 1, block,
3055ca4e4beSPekka Enberg 			    sizeof(struct tag));
306f2844803SJan Kara 	iter->fi.fileVersionNum = cpu_to_le16(1);
307f2844803SJan Kara 	iter->fi.lengthFileIdent = namelen;
308f2844803SJan Kara 	iter->fi.lengthOfImpUse = cpu_to_le16(0);
309f2844803SJan Kara 	memcpy(iter->namebuf, name, namelen);
310f2844803SJan Kara 	iter->name = iter->namebuf;
311f2844803SJan Kara 
3121da177e4SLinus Torvalds 	dir->i_size += nfidlen;
313f2844803SJan Kara 	if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
31448d6d8ffSMarcin Slusarz 		dinfo->i_lenAlloc += nfidlen;
315cb00ea35SCyrill Gorcunov 	} else {
316f2844803SJan Kara 		/* Truncate last extent to proper size */
317f2844803SJan Kara 		udf_fiiter_update_elen(iter, iter->elen -
318f2844803SJan Kara 					(dinfo->i_lenExtents - dir->i_size));
319f2844803SJan Kara 	}
320f2844803SJan Kara 	mark_inode_dirty(dir);
321f2844803SJan Kara 
322f2844803SJan Kara 	return 0;
323b80697c1SJan Kara }
324b80697c1SJan Kara 
udf_fiiter_delete_entry(struct udf_fileident_iter * iter)3254cca7e3dSJan Kara static void udf_fiiter_delete_entry(struct udf_fileident_iter *iter)
3261da177e4SLinus Torvalds {
3274cca7e3dSJan Kara 	iter->fi.fileCharacteristics |= FID_FILE_CHAR_DELETED;
32828de7948SCyrill Gorcunov 
3294cca7e3dSJan Kara 	if (UDF_QUERY_FLAG(iter->dir->i_sb, UDF_FLAG_STRICT))
3304cca7e3dSJan Kara 		memset(&iter->fi.icb, 0x00, sizeof(struct long_ad));
33128de7948SCyrill Gorcunov 
3324cca7e3dSJan Kara 	udf_fiiter_write_fi(iter, NULL);
3334cca7e3dSJan Kara }
3344cca7e3dSJan Kara 
udf_add_fid_counter(struct super_block * sb,bool dir,int val)335085cf7b7SJan Kara static void udf_add_fid_counter(struct super_block *sb, bool dir, int val)
336085cf7b7SJan Kara {
337085cf7b7SJan Kara 	struct logicalVolIntegrityDescImpUse *lvidiu = udf_sb_lvidiu(sb);
338085cf7b7SJan Kara 
339085cf7b7SJan Kara 	if (!lvidiu)
340085cf7b7SJan Kara 		return;
341085cf7b7SJan Kara 	mutex_lock(&UDF_SB(sb)->s_alloc_mutex);
342085cf7b7SJan Kara 	if (dir)
343085cf7b7SJan Kara 		le32_add_cpu(&lvidiu->numDirs, val);
344085cf7b7SJan Kara 	else
345085cf7b7SJan Kara 		le32_add_cpu(&lvidiu->numFiles, val);
346085cf7b7SJan Kara 	udf_updated_lvid(sb);
347085cf7b7SJan Kara 	mutex_unlock(&UDF_SB(sb)->s_alloc_mutex);
3481da177e4SLinus Torvalds }
3491da177e4SLinus Torvalds 
udf_add_nondir(struct dentry * dentry,struct inode * inode)350d2be51cbSAl Viro static int udf_add_nondir(struct dentry *dentry, struct inode *inode)
3511da177e4SLinus Torvalds {
352d2be51cbSAl Viro 	struct udf_inode_info *iinfo = UDF_I(inode);
3532b0143b5SDavid Howells 	struct inode *dir = d_inode(dentry->d_parent);
354ef91f999SJan Kara 	struct udf_fileident_iter iter;
3551da177e4SLinus Torvalds 	int err;
3561da177e4SLinus Torvalds 
357ef91f999SJan Kara 	err = udf_fiiter_add_entry(dir, dentry, &iter);
358ef91f999SJan Kara 	if (err) {
3596d6b77f1SMiklos Szeredi 		inode_dec_link_count(inode);
3605c1a68a3SAl Viro 		discard_new_inode(inode);
3611da177e4SLinus Torvalds 		return err;
3621da177e4SLinus Torvalds 	}
363ef91f999SJan Kara 	iter.fi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
364ef91f999SJan Kara 	iter.fi.icb.extLocation = cpu_to_lelb(iinfo->i_location);
365ef91f999SJan Kara 	*(__le32 *)((struct allocDescImpUse *)iter.fi.icb.impUse)->impUse =
36648d6d8ffSMarcin Slusarz 		cpu_to_le32(iinfo->i_unique & 0x00000000FFFFFFFFUL);
367ef91f999SJan Kara 	udf_fiiter_write_fi(&iter, NULL);
368*59ad88f2SJeff Layton 	dir->i_mtime = inode_set_ctime_current(dir);
3691da177e4SLinus Torvalds 	mark_inode_dirty(dir);
370ef91f999SJan Kara 	udf_fiiter_release(&iter);
371085cf7b7SJan Kara 	udf_add_fid_counter(dir->i_sb, false, 1);
3721e2e547aSAl Viro 	d_instantiate_new(dentry, inode);
37328de7948SCyrill Gorcunov 
3741da177e4SLinus Torvalds 	return 0;
3751da177e4SLinus Torvalds }
3761da177e4SLinus Torvalds 
udf_create(struct mnt_idmap * idmap,struct inode * dir,struct dentry * dentry,umode_t mode,bool excl)3776c960e68SChristian Brauner static int udf_create(struct mnt_idmap *idmap, struct inode *dir,
378549c7297SChristian Brauner 		      struct dentry *dentry, umode_t mode, bool excl)
379d2be51cbSAl Viro {
3800b93a92bSAl Viro 	struct inode *inode = udf_new_inode(dir, mode);
381d2be51cbSAl Viro 
3820b93a92bSAl Viro 	if (IS_ERR(inode))
3830b93a92bSAl Viro 		return PTR_ERR(inode);
384d2be51cbSAl Viro 
385d2be51cbSAl Viro 	inode->i_data.a_ops = &udf_aops;
386d2be51cbSAl Viro 	inode->i_op = &udf_file_inode_operations;
387d2be51cbSAl Viro 	inode->i_fop = &udf_file_operations;
388d2be51cbSAl Viro 	mark_inode_dirty(inode);
389d2be51cbSAl Viro 
390d2be51cbSAl Viro 	return udf_add_nondir(dentry, inode);
391d2be51cbSAl Viro }
392d2be51cbSAl Viro 
udf_tmpfile(struct mnt_idmap * idmap,struct inode * dir,struct file * file,umode_t mode)393011e2b71SChristian Brauner static int udf_tmpfile(struct mnt_idmap *idmap, struct inode *dir,
394863f144fSMiklos Szeredi 		       struct file *file, umode_t mode)
395656d09dfSAl Viro {
3960b93a92bSAl Viro 	struct inode *inode = udf_new_inode(dir, mode);
397656d09dfSAl Viro 
3980b93a92bSAl Viro 	if (IS_ERR(inode))
3990b93a92bSAl Viro 		return PTR_ERR(inode);
400656d09dfSAl Viro 
401656d09dfSAl Viro 	inode->i_data.a_ops = &udf_aops;
402656d09dfSAl Viro 	inode->i_op = &udf_file_inode_operations;
403656d09dfSAl Viro 	inode->i_fop = &udf_file_operations;
404656d09dfSAl Viro 	mark_inode_dirty(inode);
405863f144fSMiklos Szeredi 	d_tmpfile(file, inode);
406b2315096SAl Viro 	unlock_new_inode(inode);
407863f144fSMiklos Szeredi 	return finish_open_simple(file, 0);
408656d09dfSAl Viro }
409656d09dfSAl Viro 
udf_mknod(struct mnt_idmap * idmap,struct inode * dir,struct dentry * dentry,umode_t mode,dev_t rdev)4105ebb29beSChristian Brauner static int udf_mknod(struct mnt_idmap *idmap, struct inode *dir,
411549c7297SChristian Brauner 		     struct dentry *dentry, umode_t mode, dev_t rdev)
4121da177e4SLinus Torvalds {
4131da177e4SLinus Torvalds 	struct inode *inode;
4141da177e4SLinus Torvalds 
4151da177e4SLinus Torvalds 	if (!old_valid_dev(rdev))
4161da177e4SLinus Torvalds 		return -EINVAL;
4171da177e4SLinus Torvalds 
4180b93a92bSAl Viro 	inode = udf_new_inode(dir, mode);
4190b93a92bSAl Viro 	if (IS_ERR(inode))
4200b93a92bSAl Viro 		return PTR_ERR(inode);
4211da177e4SLinus Torvalds 
4221da177e4SLinus Torvalds 	init_special_inode(inode, mode, rdev);
423d2be51cbSAl Viro 	return udf_add_nondir(dentry, inode);
4241da177e4SLinus Torvalds }
4251da177e4SLinus Torvalds 
udf_mkdir(struct mnt_idmap * idmap,struct inode * dir,struct dentry * dentry,umode_t mode)426c54bd91eSChristian Brauner static int udf_mkdir(struct mnt_idmap *idmap, struct inode *dir,
427549c7297SChristian Brauner 		     struct dentry *dentry, umode_t mode)
4281da177e4SLinus Torvalds {
4291da177e4SLinus Torvalds 	struct inode *inode;
43000bce6f7SJan Kara 	struct udf_fileident_iter iter;
4311da177e4SLinus Torvalds 	int err;
43248d6d8ffSMarcin Slusarz 	struct udf_inode_info *dinfo = UDF_I(dir);
43348d6d8ffSMarcin Slusarz 	struct udf_inode_info *iinfo;
4341da177e4SLinus Torvalds 
4350b93a92bSAl Viro 	inode = udf_new_inode(dir, S_IFDIR | mode);
4360b93a92bSAl Viro 	if (IS_ERR(inode))
4370b93a92bSAl Viro 		return PTR_ERR(inode);
4381da177e4SLinus Torvalds 
43948d6d8ffSMarcin Slusarz 	iinfo = UDF_I(inode);
4401da177e4SLinus Torvalds 	inode->i_op = &udf_dir_inode_operations;
4411da177e4SLinus Torvalds 	inode->i_fop = &udf_dir_operations;
44200bce6f7SJan Kara 	err = udf_fiiter_add_entry(inode, NULL, &iter);
44300bce6f7SJan Kara 	if (err) {
44400bce6f7SJan Kara 		clear_nlink(inode);
4455c1a68a3SAl Viro 		discard_new_inode(inode);
44600bce6f7SJan Kara 		return err;
4471da177e4SLinus Torvalds 	}
448bfe86848SMiklos Szeredi 	set_nlink(inode, 2);
44900bce6f7SJan Kara 	iter.fi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
45000bce6f7SJan Kara 	iter.fi.icb.extLocation = cpu_to_lelb(dinfo->i_location);
45100bce6f7SJan Kara 	*(__le32 *)((struct allocDescImpUse *)iter.fi.icb.impUse)->impUse =
45248d6d8ffSMarcin Slusarz 		cpu_to_le32(dinfo->i_unique & 0x00000000FFFFFFFFUL);
45300bce6f7SJan Kara 	iter.fi.fileCharacteristics =
4544b11111aSMarcin Slusarz 			FID_FILE_CHAR_DIRECTORY | FID_FILE_CHAR_PARENT;
45500bce6f7SJan Kara 	udf_fiiter_write_fi(&iter, NULL);
45600bce6f7SJan Kara 	udf_fiiter_release(&iter);
4571da177e4SLinus Torvalds 	mark_inode_dirty(inode);
4581da177e4SLinus Torvalds 
45900bce6f7SJan Kara 	err = udf_fiiter_add_entry(dir, dentry, &iter);
46000bce6f7SJan Kara 	if (err) {
4616d6b77f1SMiklos Szeredi 		clear_nlink(inode);
4625c1a68a3SAl Viro 		discard_new_inode(inode);
46300bce6f7SJan Kara 		return err;
4641da177e4SLinus Torvalds 	}
46500bce6f7SJan Kara 	iter.fi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
46600bce6f7SJan Kara 	iter.fi.icb.extLocation = cpu_to_lelb(iinfo->i_location);
46700bce6f7SJan Kara 	*(__le32 *)((struct allocDescImpUse *)iter.fi.icb.impUse)->impUse =
46848d6d8ffSMarcin Slusarz 		cpu_to_le32(iinfo->i_unique & 0x00000000FFFFFFFFUL);
46900bce6f7SJan Kara 	iter.fi.fileCharacteristics |= FID_FILE_CHAR_DIRECTORY;
47000bce6f7SJan Kara 	udf_fiiter_write_fi(&iter, NULL);
47100bce6f7SJan Kara 	udf_fiiter_release(&iter);
472085cf7b7SJan Kara 	udf_add_fid_counter(dir->i_sb, true, 1);
473d8c76e6fSDave Hansen 	inc_nlink(dir);
474*59ad88f2SJeff Layton 	dir->i_mtime = inode_set_ctime_current(dir);
4751da177e4SLinus Torvalds 	mark_inode_dirty(dir);
4761e2e547aSAl Viro 	d_instantiate_new(dentry, inode);
47728de7948SCyrill Gorcunov 
47800bce6f7SJan Kara 	return 0;
4791da177e4SLinus Torvalds }
4801da177e4SLinus Torvalds 
empty_dir(struct inode * dir)4811da177e4SLinus Torvalds static int empty_dir(struct inode *dir)
4821da177e4SLinus Torvalds {
483afb525f4SJan Kara 	struct udf_fileident_iter iter;
484afb525f4SJan Kara 	int ret;
4851da177e4SLinus Torvalds 
486afb525f4SJan Kara 	for (ret = udf_fiiter_init(&iter, dir, 0);
487afb525f4SJan Kara 	     !ret && iter.pos < dir->i_size;
488afb525f4SJan Kara 	     ret = udf_fiiter_advance(&iter)) {
489afb525f4SJan Kara 		if (iter.fi.lengthFileIdent &&
490afb525f4SJan Kara 		    !(iter.fi.fileCharacteristics & FID_FILE_CHAR_DELETED)) {
491afb525f4SJan Kara 			udf_fiiter_release(&iter);
4921da177e4SLinus Torvalds 			return 0;
4931da177e4SLinus Torvalds 		}
4941da177e4SLinus Torvalds 	}
495afb525f4SJan Kara 	udf_fiiter_release(&iter);
49628de7948SCyrill Gorcunov 
4971da177e4SLinus Torvalds 	return 1;
4981da177e4SLinus Torvalds }
4991da177e4SLinus Torvalds 
udf_rmdir(struct inode * dir,struct dentry * dentry)5001da177e4SLinus Torvalds static int udf_rmdir(struct inode *dir, struct dentry *dentry)
5011da177e4SLinus Torvalds {
502d11ffa8dSJan Kara 	int ret;
5032b0143b5SDavid Howells 	struct inode *inode = d_inode(dentry);
504d11ffa8dSJan Kara 	struct udf_fileident_iter iter;
5055ca4e4beSPekka Enberg 	struct kernel_lb_addr tloc;
5061da177e4SLinus Torvalds 
507d11ffa8dSJan Kara 	ret = udf_fiiter_find_entry(dir, &dentry->d_name, &iter);
508d11ffa8dSJan Kara 	if (ret)
5091da177e4SLinus Torvalds 		goto out;
5101da177e4SLinus Torvalds 
511d11ffa8dSJan Kara 	ret = -EFSCORRUPTED;
512d11ffa8dSJan Kara 	tloc = lelb_to_cpu(iter.fi.icb.extLocation);
51397e961fdSPekka Enberg 	if (udf_get_lb_pblock(dir->i_sb, &tloc, 0) != inode->i_ino)
5141da177e4SLinus Torvalds 		goto end_rmdir;
515d11ffa8dSJan Kara 	ret = -ENOTEMPTY;
5161da177e4SLinus Torvalds 	if (!empty_dir(inode))
5171da177e4SLinus Torvalds 		goto end_rmdir;
518d11ffa8dSJan Kara 	udf_fiiter_delete_entry(&iter);
5191da177e4SLinus Torvalds 	if (inode->i_nlink != 2)
520fcbf7637SSteve Magnani 		udf_warn(inode->i_sb, "empty directory has nlink != 2 (%u)\n",
5211da177e4SLinus Torvalds 			 inode->i_nlink);
522ce71ec36SDave Hansen 	clear_nlink(inode);
5231da177e4SLinus Torvalds 	inode->i_size = 0;
524c007c06eSStephen Mollett 	inode_dec_link_count(dir);
525085cf7b7SJan Kara 	udf_add_fid_counter(dir->i_sb, true, -1);
526*59ad88f2SJeff Layton 	dir->i_mtime = inode_set_ctime_to_ts(dir,
527*59ad88f2SJeff Layton 					     inode_set_ctime_current(inode));
5281da177e4SLinus Torvalds 	mark_inode_dirty(dir);
529d11ffa8dSJan Kara 	ret = 0;
5301da177e4SLinus Torvalds end_rmdir:
531d11ffa8dSJan Kara 	udf_fiiter_release(&iter);
5321da177e4SLinus Torvalds out:
533d11ffa8dSJan Kara 	return ret;
5341da177e4SLinus Torvalds }
5351da177e4SLinus Torvalds 
udf_unlink(struct inode * dir,struct dentry * dentry)5361da177e4SLinus Torvalds static int udf_unlink(struct inode *dir, struct dentry *dentry)
5371da177e4SLinus Torvalds {
5386ec01a80SJan Kara 	int ret;
5392b0143b5SDavid Howells 	struct inode *inode = d_inode(dentry);
5406ec01a80SJan Kara 	struct udf_fileident_iter iter;
5415ca4e4beSPekka Enberg 	struct kernel_lb_addr tloc;
5421da177e4SLinus Torvalds 
5436ec01a80SJan Kara 	ret = udf_fiiter_find_entry(dir, &dentry->d_name, &iter);
5446ec01a80SJan Kara 	if (ret)
5451da177e4SLinus Torvalds 		goto out;
5461da177e4SLinus Torvalds 
5476ec01a80SJan Kara 	ret = -EFSCORRUPTED;
5486ec01a80SJan Kara 	tloc = lelb_to_cpu(iter.fi.icb.extLocation);
54997e961fdSPekka Enberg 	if (udf_get_lb_pblock(dir->i_sb, &tloc, 0) != inode->i_ino)
5501da177e4SLinus Torvalds 		goto end_unlink;
5511da177e4SLinus Torvalds 
552cb00ea35SCyrill Gorcunov 	if (!inode->i_nlink) {
553fcbf7637SSteve Magnani 		udf_debug("Deleting nonexistent file (%lu), %u\n",
5541da177e4SLinus Torvalds 			  inode->i_ino, inode->i_nlink);
555bfe86848SMiklos Szeredi 		set_nlink(inode, 1);
5561da177e4SLinus Torvalds 	}
5576ec01a80SJan Kara 	udf_fiiter_delete_entry(&iter);
558*59ad88f2SJeff Layton 	dir->i_mtime = inode_set_ctime_current(dir);
5591da177e4SLinus Torvalds 	mark_inode_dirty(dir);
5609a53c3a7SDave Hansen 	inode_dec_link_count(inode);
561085cf7b7SJan Kara 	udf_add_fid_counter(dir->i_sb, false, -1);
562*59ad88f2SJeff Layton 	inode_set_ctime_to_ts(inode, inode_get_ctime(dir));
5636ec01a80SJan Kara 	ret = 0;
5641da177e4SLinus Torvalds end_unlink:
5656ec01a80SJan Kara 	udf_fiiter_release(&iter);
5661da177e4SLinus Torvalds out:
5676ec01a80SJan Kara 	return ret;
5681da177e4SLinus Torvalds }
5691da177e4SLinus Torvalds 
udf_symlink(struct mnt_idmap * idmap,struct inode * dir,struct dentry * dentry,const char * symname)5707a77db95SChristian Brauner static int udf_symlink(struct mnt_idmap *idmap, struct inode *dir,
571549c7297SChristian Brauner 		       struct dentry *dentry, const char *symname)
5721da177e4SLinus Torvalds {
5736ff6b2b3SFabian Frederick 	struct inode *inode = udf_new_inode(dir, S_IFLNK | 0777);
5741da177e4SLinus Torvalds 	struct pathComponent *pc;
575391e8bbdSAl Viro 	const char *compstart;
57628de7948SCyrill Gorcunov 	struct extent_position epos = {};
5771da177e4SLinus Torvalds 	int eoffset, elen = 0;
578391e8bbdSAl Viro 	uint8_t *ea;
5791da177e4SLinus Torvalds 	int err;
580b490bdd6SSteve Magnani 	udf_pblk_t block;
581391e8bbdSAl Viro 	unsigned char *name = NULL;
5821da177e4SLinus Torvalds 	int namelen;
58348d6d8ffSMarcin Slusarz 	struct udf_inode_info *iinfo;
584d664b6afSJan Kara 	struct super_block *sb = dir->i_sb;
5851da177e4SLinus Torvalds 
5860b93a92bSAl Viro 	if (IS_ERR(inode))
5870b93a92bSAl Viro 		return PTR_ERR(inode);
5881da177e4SLinus Torvalds 
5894d0fb621SAlessio Igor Bogani 	iinfo = UDF_I(inode);
5904d0fb621SAlessio Igor Bogani 	down_write(&iinfo->i_data_sem);
5919fba7056SAndrew Gabbasov 	name = kmalloc(UDF_NAME_LEN_CS0, GFP_NOFS);
592b80697c1SJan Kara 	if (!name) {
593b80697c1SJan Kara 		err = -ENOMEM;
594b80697c1SJan Kara 		goto out_no_entry;
595b80697c1SJan Kara 	}
596b80697c1SJan Kara 
5971da177e4SLinus Torvalds 	inode->i_data.a_ops = &udf_symlink_aops;
598ad4d0532SJan Kara 	inode->i_op = &udf_symlink_inode_operations;
59921fc61c7SAl Viro 	inode_nohighmem(inode);
6001da177e4SLinus Torvalds 
60148d6d8ffSMarcin Slusarz 	if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) {
6025ca4e4beSPekka Enberg 		struct kernel_lb_addr eloc;
60378e917d5SHarvey Harrison 		uint32_t bsize;
6041da177e4SLinus Torvalds 
605d664b6afSJan Kara 		block = udf_new_block(sb, inode,
60648d6d8ffSMarcin Slusarz 				iinfo->i_location.partitionReferenceNum,
60748d6d8ffSMarcin Slusarz 				iinfo->i_location.logicalBlockNum, &err);
6081da177e4SLinus Torvalds 		if (!block)
6091da177e4SLinus Torvalds 			goto out_no_entry;
61048d6d8ffSMarcin Slusarz 		epos.block = iinfo->i_location;
611ff116fc8SJan Kara 		epos.offset = udf_file_entry_alloc_offset(inode);
612ff116fc8SJan Kara 		epos.bh = NULL;
6131da177e4SLinus Torvalds 		eloc.logicalBlockNum = block;
6144b11111aSMarcin Slusarz 		eloc.partitionReferenceNum =
61548d6d8ffSMarcin Slusarz 				iinfo->i_location.partitionReferenceNum;
616d664b6afSJan Kara 		bsize = sb->s_blocksize;
61778e917d5SHarvey Harrison 		iinfo->i_lenExtents = bsize;
6182b10074dSJan Kara 		err = udf_add_aext(inode, &epos, &eloc, bsize, 0);
6193bf25cb4SJan Kara 		brelse(epos.bh);
6202b10074dSJan Kara 		if (err < 0) {
6212b10074dSJan Kara 			udf_free_blocks(sb, inode, &eloc, 0, 1);
6222b10074dSJan Kara 			goto out_no_entry;
6232b10074dSJan Kara 		}
6241da177e4SLinus Torvalds 
625d664b6afSJan Kara 		block = udf_get_pblock(sb, block,
62648d6d8ffSMarcin Slusarz 				iinfo->i_location.partitionReferenceNum,
6274b11111aSMarcin Slusarz 				0);
628101ee137SJan Kara 		epos.bh = sb_getblk(sb, block);
629fa236c2bSArturo Giusti 		if (unlikely(!epos.bh)) {
630fa236c2bSArturo Giusti 			err = -ENOMEM;
6312b10074dSJan Kara 			udf_free_blocks(sb, inode, &eloc, 0, 1);
632fa236c2bSArturo Giusti 			goto out_no_entry;
633fa236c2bSArturo Giusti 		}
634ff116fc8SJan Kara 		lock_buffer(epos.bh);
635d664b6afSJan Kara 		memset(epos.bh->b_data, 0x00, bsize);
636ff116fc8SJan Kara 		set_buffer_uptodate(epos.bh);
637ff116fc8SJan Kara 		unlock_buffer(epos.bh);
638ff116fc8SJan Kara 		mark_buffer_dirty_inode(epos.bh, inode);
639ff116fc8SJan Kara 		ea = epos.bh->b_data + udf_ext0_offset(inode);
64048d6d8ffSMarcin Slusarz 	} else
641382a2287SJan Kara 		ea = iinfo->i_data + iinfo->i_lenEAttr;
6421da177e4SLinus Torvalds 
643d664b6afSJan Kara 	eoffset = sb->s_blocksize - udf_ext0_offset(inode);
6441da177e4SLinus Torvalds 	pc = (struct pathComponent *)ea;
6451da177e4SLinus Torvalds 
646cb00ea35SCyrill Gorcunov 	if (*symname == '/') {
647cb00ea35SCyrill Gorcunov 		do {
6481da177e4SLinus Torvalds 			symname++;
6491da177e4SLinus Torvalds 		} while (*symname == '/');
6501da177e4SLinus Torvalds 
6511da177e4SLinus Torvalds 		pc->componentType = 1;
6521da177e4SLinus Torvalds 		pc->lengthComponentIdent = 0;
6531da177e4SLinus Torvalds 		pc->componentFileVersionNum = 0;
6541da177e4SLinus Torvalds 		elen += sizeof(struct pathComponent);
6551da177e4SLinus Torvalds 	}
6561da177e4SLinus Torvalds 
6571da177e4SLinus Torvalds 	err = -ENAMETOOLONG;
6581da177e4SLinus Torvalds 
659cb00ea35SCyrill Gorcunov 	while (*symname) {
6601da177e4SLinus Torvalds 		if (elen + sizeof(struct pathComponent) > eoffset)
6611da177e4SLinus Torvalds 			goto out_no_entry;
6621da177e4SLinus Torvalds 
6631da177e4SLinus Torvalds 		pc = (struct pathComponent *)(ea + elen);
6641da177e4SLinus Torvalds 
665391e8bbdSAl Viro 		compstart = symname;
6661da177e4SLinus Torvalds 
667cb00ea35SCyrill Gorcunov 		do {
6681da177e4SLinus Torvalds 			symname++;
6691da177e4SLinus Torvalds 		} while (*symname && *symname != '/');
6701da177e4SLinus Torvalds 
6711da177e4SLinus Torvalds 		pc->componentType = 5;
6721da177e4SLinus Torvalds 		pc->lengthComponentIdent = 0;
6731da177e4SLinus Torvalds 		pc->componentFileVersionNum = 0;
674cb00ea35SCyrill Gorcunov 		if (compstart[0] == '.') {
6751da177e4SLinus Torvalds 			if ((symname - compstart) == 1)
6761da177e4SLinus Torvalds 				pc->componentType = 4;
6774b11111aSMarcin Slusarz 			else if ((symname - compstart) == 2 &&
6784b11111aSMarcin Slusarz 					compstart[1] == '.')
6791da177e4SLinus Torvalds 				pc->componentType = 3;
6801da177e4SLinus Torvalds 		}
6811da177e4SLinus Torvalds 
682cb00ea35SCyrill Gorcunov 		if (pc->componentType == 5) {
683525e2c56SAndrew Gabbasov 			namelen = udf_put_filename(sb, compstart,
684525e2c56SAndrew Gabbasov 						   symname - compstart,
6859fba7056SAndrew Gabbasov 						   name, UDF_NAME_LEN_CS0);
68628de7948SCyrill Gorcunov 			if (!namelen)
6871da177e4SLinus Torvalds 				goto out_no_entry;
6881da177e4SLinus Torvalds 
6894b11111aSMarcin Slusarz 			if (elen + sizeof(struct pathComponent) + namelen >
6904b11111aSMarcin Slusarz 					eoffset)
6911da177e4SLinus Torvalds 				goto out_no_entry;
6921da177e4SLinus Torvalds 			else
6931da177e4SLinus Torvalds 				pc->lengthComponentIdent = namelen;
6941da177e4SLinus Torvalds 
6951da177e4SLinus Torvalds 			memcpy(pc->componentIdent, name, namelen);
6961da177e4SLinus Torvalds 		}
6971da177e4SLinus Torvalds 
6981da177e4SLinus Torvalds 		elen += sizeof(struct pathComponent) + pc->lengthComponentIdent;
6991da177e4SLinus Torvalds 
700cb00ea35SCyrill Gorcunov 		if (*symname) {
701cb00ea35SCyrill Gorcunov 			do {
7021da177e4SLinus Torvalds 				symname++;
7031da177e4SLinus Torvalds 			} while (*symname == '/');
7041da177e4SLinus Torvalds 		}
7051da177e4SLinus Torvalds 	}
7061da177e4SLinus Torvalds 
7073bf25cb4SJan Kara 	brelse(epos.bh);
7081da177e4SLinus Torvalds 	inode->i_size = elen;
70948d6d8ffSMarcin Slusarz 	if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
71048d6d8ffSMarcin Slusarz 		iinfo->i_lenAlloc = inode->i_size;
7112c948b3fSJan Kara 	else
7122c948b3fSJan Kara 		udf_truncate_tail_extent(inode);
7131da177e4SLinus Torvalds 	mark_inode_dirty(inode);
7144ea7772fSJan Kara 	up_write(&iinfo->i_data_sem);
7151da177e4SLinus Torvalds 
716d2be51cbSAl Viro 	err = udf_add_nondir(dentry, inode);
7171da177e4SLinus Torvalds out:
718b80697c1SJan Kara 	kfree(name);
7191da177e4SLinus Torvalds 	return err;
7201da177e4SLinus Torvalds 
7211da177e4SLinus Torvalds out_no_entry:
7224d0fb621SAlessio Igor Bogani 	up_write(&iinfo->i_data_sem);
7239a53c3a7SDave Hansen 	inode_dec_link_count(inode);
7245c1a68a3SAl Viro 	discard_new_inode(inode);
7251da177e4SLinus Torvalds 	goto out;
7261da177e4SLinus Torvalds }
7271da177e4SLinus Torvalds 
udf_link(struct dentry * old_dentry,struct inode * dir,struct dentry * dentry)7281da177e4SLinus Torvalds static int udf_link(struct dentry *old_dentry, struct inode *dir,
7291da177e4SLinus Torvalds 		    struct dentry *dentry)
7301da177e4SLinus Torvalds {
7312b0143b5SDavid Howells 	struct inode *inode = d_inode(old_dentry);
732dbfb102dSJan Kara 	struct udf_fileident_iter iter;
7331da177e4SLinus Torvalds 	int err;
7341da177e4SLinus Torvalds 
735dbfb102dSJan Kara 	err = udf_fiiter_add_entry(dir, dentry, &iter);
736dbfb102dSJan Kara 	if (err)
7371da177e4SLinus Torvalds 		return err;
738dbfb102dSJan Kara 	iter.fi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
739dbfb102dSJan Kara 	iter.fi.icb.extLocation = cpu_to_lelb(UDF_I(inode)->i_location);
740d664b6afSJan Kara 	if (UDF_SB(inode->i_sb)->s_lvid_bh) {
741dbfb102dSJan Kara 		*(__le32 *)((struct allocDescImpUse *)iter.fi.icb.impUse)->impUse =
742d664b6afSJan Kara 			cpu_to_le32(lvid_get_unique_id(inode->i_sb));
7431da177e4SLinus Torvalds 	}
744dbfb102dSJan Kara 	udf_fiiter_write_fi(&iter, NULL);
745dbfb102dSJan Kara 	udf_fiiter_release(&iter);
74628de7948SCyrill Gorcunov 
747d8c76e6fSDave Hansen 	inc_nlink(inode);
748085cf7b7SJan Kara 	udf_add_fid_counter(dir->i_sb, false, 1);
749*59ad88f2SJeff Layton 	inode_set_ctime_current(inode);
7501da177e4SLinus Torvalds 	mark_inode_dirty(inode);
751*59ad88f2SJeff Layton 	dir->i_mtime = inode_set_ctime_current(dir);
7523adc12e9SJan Kara 	mark_inode_dirty(dir);
7537de9c6eeSAl Viro 	ihold(inode);
7541da177e4SLinus Torvalds 	d_instantiate(dentry, inode);
75528de7948SCyrill Gorcunov 
7561da177e4SLinus Torvalds 	return 0;
7571da177e4SLinus Torvalds }
7581da177e4SLinus Torvalds 
7591da177e4SLinus Torvalds /* Anybody can rename anything with this: the permission checks are left to the
7601da177e4SLinus Torvalds  * higher-level routines.
7611da177e4SLinus Torvalds  */
udf_rename(struct mnt_idmap * idmap,struct inode * old_dir,struct dentry * old_dentry,struct inode * new_dir,struct dentry * new_dentry,unsigned int flags)762e18275aeSChristian Brauner static int udf_rename(struct mnt_idmap *idmap, struct inode *old_dir,
763549c7297SChristian Brauner 		      struct dentry *old_dentry, struct inode *new_dir,
764549c7297SChristian Brauner 		      struct dentry *new_dentry, unsigned int flags)
7651da177e4SLinus Torvalds {
7662b0143b5SDavid Howells 	struct inode *old_inode = d_inode(old_dentry);
7672b0143b5SDavid Howells 	struct inode *new_inode = d_inode(new_dentry);
768e9109a92SJan Kara 	struct udf_fileident_iter oiter, niter, diriter;
769e9109a92SJan Kara 	bool has_diriter = false;
770e9109a92SJan Kara 	int retval;
7715ca4e4beSPekka Enberg 	struct kernel_lb_addr tloc;
7721da177e4SLinus Torvalds 
773f03b8ad8SMiklos Szeredi 	if (flags & ~RENAME_NOREPLACE)
774f03b8ad8SMiklos Szeredi 		return -EINVAL;
775f03b8ad8SMiklos Szeredi 
776e9109a92SJan Kara 	retval = udf_fiiter_find_entry(old_dir, &old_dentry->d_name, &oiter);
777e9109a92SJan Kara 	if (retval)
778e9109a92SJan Kara 		return retval;
779e9109a92SJan Kara 
780e9109a92SJan Kara 	tloc = lelb_to_cpu(oiter.fi.icb.extLocation);
781e9109a92SJan Kara 	if (udf_get_lb_pblock(old_dir->i_sb, &tloc, 0) != old_inode->i_ino) {
782e9109a92SJan Kara 		retval = -ENOENT;
783e9109a92SJan Kara 		goto out_oiter;
784231473f6SFabian Frederick 	}
785231473f6SFabian Frederick 
786cb00ea35SCyrill Gorcunov 	if (S_ISDIR(old_inode->i_mode)) {
787cb00ea35SCyrill Gorcunov 		if (new_inode) {
7881da177e4SLinus Torvalds 			retval = -ENOTEMPTY;
7891da177e4SLinus Torvalds 			if (!empty_dir(new_inode))
790e9109a92SJan Kara 				goto out_oiter;
7911da177e4SLinus Torvalds 		}
792e9109a92SJan Kara 		retval = udf_fiiter_find_entry(old_inode, &dotdot_name,
793e9109a92SJan Kara 					       &diriter);
794e9109a92SJan Kara 		if (retval == -ENOENT) {
795e9109a92SJan Kara 			udf_err(old_inode->i_sb,
796e9109a92SJan Kara 				"directory (ino %lu) has no '..' entry\n",
797e9109a92SJan Kara 				old_inode->i_ino);
798e9109a92SJan Kara 			retval = -EFSCORRUPTED;
7991da177e4SLinus Torvalds 		}
8007517ce5dSJan Kara 		if (retval)
801e9109a92SJan Kara 			goto out_oiter;
802e9109a92SJan Kara 		has_diriter = true;
803e9109a92SJan Kara 		tloc = lelb_to_cpu(diriter.fi.icb.extLocation);
80497e961fdSPekka Enberg 		if (udf_get_lb_pblock(old_inode->i_sb, &tloc, 0) !=
805e9109a92SJan Kara 				old_dir->i_ino) {
806e9109a92SJan Kara 			retval = -EFSCORRUPTED;
807e9109a92SJan Kara 			udf_err(old_inode->i_sb,
808e9109a92SJan Kara 				"directory (ino %lu) has parent entry pointing to another inode (%lu != %u)\n",
809e9109a92SJan Kara 				old_inode->i_ino, old_dir->i_ino,
810e9109a92SJan Kara 				udf_get_lb_pblock(old_inode->i_sb, &tloc, 0));
811e9109a92SJan Kara 			goto out_oiter;
8121da177e4SLinus Torvalds 		}
813e9109a92SJan Kara 	}
814e9109a92SJan Kara 
815e9109a92SJan Kara 	retval = udf_fiiter_find_entry(new_dir, &new_dentry->d_name, &niter);
816e9109a92SJan Kara 	if (retval && retval != -ENOENT)
817e9109a92SJan Kara 		goto out_oiter;
818e9109a92SJan Kara 	/* Entry found but not passed by VFS? */
819e9109a92SJan Kara 	if (!retval && !new_inode) {
820e9109a92SJan Kara 		retval = -EFSCORRUPTED;
821e9109a92SJan Kara 		udf_fiiter_release(&niter);
822e9109a92SJan Kara 		goto out_oiter;
823e9109a92SJan Kara 	}
824e9109a92SJan Kara 	/* Entry not found? Need to add one... */
825e9109a92SJan Kara 	if (retval) {
826e9109a92SJan Kara 		udf_fiiter_release(&niter);
827e9109a92SJan Kara 		retval = udf_fiiter_add_entry(new_dir, new_dentry, &niter);
828e9109a92SJan Kara 		if (retval)
829e9109a92SJan Kara 			goto out_oiter;
8301da177e4SLinus Torvalds 	}
8311da177e4SLinus Torvalds 
8321da177e4SLinus Torvalds 	/*
8331da177e4SLinus Torvalds 	 * Like most other Unix systems, set the ctime for inodes on a
8341da177e4SLinus Torvalds 	 * rename.
8351da177e4SLinus Torvalds 	 */
836*59ad88f2SJeff Layton 	inode_set_ctime_current(old_inode);
8371da177e4SLinus Torvalds 	mark_inode_dirty(old_inode);
8381da177e4SLinus Torvalds 
8391da177e4SLinus Torvalds 	/*
8401da177e4SLinus Torvalds 	 * ok, that's it
8411da177e4SLinus Torvalds 	 */
842e9109a92SJan Kara 	niter.fi.fileVersionNum = oiter.fi.fileVersionNum;
843e9109a92SJan Kara 	niter.fi.fileCharacteristics = oiter.fi.fileCharacteristics;
844e9109a92SJan Kara 	memcpy(&(niter.fi.icb), &(oiter.fi.icb), sizeof(oiter.fi.icb));
845e9109a92SJan Kara 	udf_fiiter_write_fi(&niter, NULL);
846e9109a92SJan Kara 	udf_fiiter_release(&niter);
8471da177e4SLinus Torvalds 
848e9109a92SJan Kara 	/*
849e9109a92SJan Kara 	 * The old entry may have moved due to new entry allocation. Find it
850e9109a92SJan Kara 	 * again.
851e9109a92SJan Kara 	 */
852e9109a92SJan Kara 	udf_fiiter_release(&oiter);
853e9109a92SJan Kara 	retval = udf_fiiter_find_entry(old_dir, &old_dentry->d_name, &oiter);
854e9109a92SJan Kara 	if (retval) {
855e9109a92SJan Kara 		udf_err(old_dir->i_sb,
856e9109a92SJan Kara 			"failed to find renamed entry again in directory (ino %lu)\n",
857e9109a92SJan Kara 			old_dir->i_ino);
858e9109a92SJan Kara 	} else {
859e9109a92SJan Kara 		udf_fiiter_delete_entry(&oiter);
860e9109a92SJan Kara 		udf_fiiter_release(&oiter);
861e9109a92SJan Kara 	}
8621da177e4SLinus Torvalds 
863cb00ea35SCyrill Gorcunov 	if (new_inode) {
864*59ad88f2SJeff Layton 		inode_set_ctime_current(new_inode);
8659a53c3a7SDave Hansen 		inode_dec_link_count(new_inode);
866085cf7b7SJan Kara 		udf_add_fid_counter(old_dir->i_sb, S_ISDIR(new_inode->i_mode),
867085cf7b7SJan Kara 				    -1);
8681da177e4SLinus Torvalds 	}
869*59ad88f2SJeff Layton 	old_dir->i_mtime = inode_set_ctime_current(old_dir);
870*59ad88f2SJeff Layton 	new_dir->i_mtime = inode_set_ctime_current(new_dir);
8711da177e4SLinus Torvalds 	mark_inode_dirty(old_dir);
8723adc12e9SJan Kara 	mark_inode_dirty(new_dir);
8731da177e4SLinus Torvalds 
874e9109a92SJan Kara 	if (has_diriter) {
875e9109a92SJan Kara 		diriter.fi.icb.extLocation =
876e9109a92SJan Kara 					cpu_to_lelb(UDF_I(new_dir)->i_location);
877e9109a92SJan Kara 		udf_update_tag((char *)&diriter.fi,
878e9109a92SJan Kara 			       udf_dir_entry_len(&diriter.fi));
879e9109a92SJan Kara 		udf_fiiter_write_fi(&diriter, NULL);
880e9109a92SJan Kara 		udf_fiiter_release(&diriter);
8814b11111aSMarcin Slusarz 
8829a53c3a7SDave Hansen 		inode_dec_link_count(old_dir);
8834b11111aSMarcin Slusarz 		if (new_inode)
8849a53c3a7SDave Hansen 			inode_dec_link_count(new_inode);
8854b11111aSMarcin Slusarz 		else {
886d8c76e6fSDave Hansen 			inc_nlink(new_dir);
8871da177e4SLinus Torvalds 			mark_inode_dirty(new_dir);
8881da177e4SLinus Torvalds 		}
8891da177e4SLinus Torvalds 	}
890e9109a92SJan Kara 	return 0;
891e9109a92SJan Kara out_oiter:
8927517ce5dSJan Kara 	if (has_diriter)
893e9109a92SJan Kara 		udf_fiiter_release(&diriter);
894e9109a92SJan Kara 	udf_fiiter_release(&oiter);
89528de7948SCyrill Gorcunov 
8961da177e4SLinus Torvalds 	return retval;
8971da177e4SLinus Torvalds }
8981da177e4SLinus Torvalds 
udf_get_parent(struct dentry * child)899221e583aSRasmus Rohde static struct dentry *udf_get_parent(struct dentry *child)
900221e583aSRasmus Rohde {
90197e961fdSPekka Enberg 	struct kernel_lb_addr tloc;
902221e583aSRasmus Rohde 	struct inode *inode = NULL;
9039b06fbefSJan Kara 	struct udf_fileident_iter iter;
9049b06fbefSJan Kara 	int err;
905221e583aSRasmus Rohde 
9069b06fbefSJan Kara 	err = udf_fiiter_find_entry(d_inode(child), &dotdot_name, &iter);
9079b06fbefSJan Kara 	if (err)
9089b06fbefSJan Kara 		return ERR_PTR(err);
909221e583aSRasmus Rohde 
9109b06fbefSJan Kara 	tloc = lelb_to_cpu(iter.fi.icb.extLocation);
9119b06fbefSJan Kara 	udf_fiiter_release(&iter);
912fc64005cSAl Viro 	inode = udf_iget(child->d_sb, &tloc);
9136d3d5e86SJan Kara 	if (IS_ERR(inode))
9146d3d5e86SJan Kara 		return ERR_CAST(inode);
915221e583aSRasmus Rohde 
91644003728SChristoph Hellwig 	return d_obtain_alias(inode);
917221e583aSRasmus Rohde }
918221e583aSRasmus Rohde 
919221e583aSRasmus Rohde 
udf_nfs_get_inode(struct super_block * sb,u32 block,u16 partref,__u32 generation)920221e583aSRasmus Rohde static struct dentry *udf_nfs_get_inode(struct super_block *sb, u32 block,
921221e583aSRasmus Rohde 					u16 partref, __u32 generation)
922221e583aSRasmus Rohde {
923221e583aSRasmus Rohde 	struct inode *inode;
9245ca4e4beSPekka Enberg 	struct kernel_lb_addr loc;
925221e583aSRasmus Rohde 
926221e583aSRasmus Rohde 	if (block == 0)
927221e583aSRasmus Rohde 		return ERR_PTR(-ESTALE);
928221e583aSRasmus Rohde 
929221e583aSRasmus Rohde 	loc.logicalBlockNum = block;
930221e583aSRasmus Rohde 	loc.partitionReferenceNum = partref;
93197e961fdSPekka Enberg 	inode = udf_iget(sb, &loc);
932221e583aSRasmus Rohde 
9336d3d5e86SJan Kara 	if (IS_ERR(inode))
9346d3d5e86SJan Kara 		return ERR_CAST(inode);
935221e583aSRasmus Rohde 
936221e583aSRasmus Rohde 	if (generation && inode->i_generation != generation) {
937221e583aSRasmus Rohde 		iput(inode);
938221e583aSRasmus Rohde 		return ERR_PTR(-ESTALE);
939221e583aSRasmus Rohde 	}
94044003728SChristoph Hellwig 	return d_obtain_alias(inode);
941221e583aSRasmus Rohde }
942221e583aSRasmus Rohde 
udf_fh_to_dentry(struct super_block * sb,struct fid * fid,int fh_len,int fh_type)943221e583aSRasmus Rohde static struct dentry *udf_fh_to_dentry(struct super_block *sb,
944221e583aSRasmus Rohde 				       struct fid *fid, int fh_len, int fh_type)
945221e583aSRasmus Rohde {
94692acca45SNeilBrown 	if (fh_len < 3 ||
947221e583aSRasmus Rohde 	    (fh_type != FILEID_UDF_WITH_PARENT &&
948221e583aSRasmus Rohde 	     fh_type != FILEID_UDF_WITHOUT_PARENT))
949221e583aSRasmus Rohde 		return NULL;
950221e583aSRasmus Rohde 
951221e583aSRasmus Rohde 	return udf_nfs_get_inode(sb, fid->udf.block, fid->udf.partref,
952221e583aSRasmus Rohde 			fid->udf.generation);
953221e583aSRasmus Rohde }
954221e583aSRasmus Rohde 
udf_fh_to_parent(struct super_block * sb,struct fid * fid,int fh_len,int fh_type)955221e583aSRasmus Rohde static struct dentry *udf_fh_to_parent(struct super_block *sb,
956221e583aSRasmus Rohde 				       struct fid *fid, int fh_len, int fh_type)
957221e583aSRasmus Rohde {
95892acca45SNeilBrown 	if (fh_len < 5 || fh_type != FILEID_UDF_WITH_PARENT)
959221e583aSRasmus Rohde 		return NULL;
960221e583aSRasmus Rohde 
961221e583aSRasmus Rohde 	return udf_nfs_get_inode(sb, fid->udf.parent_block,
962221e583aSRasmus Rohde 				 fid->udf.parent_partref,
963221e583aSRasmus Rohde 				 fid->udf.parent_generation);
964221e583aSRasmus Rohde }
udf_encode_fh(struct inode * inode,__u32 * fh,int * lenp,struct inode * parent)965b0b0382bSAl Viro static int udf_encode_fh(struct inode *inode, __u32 *fh, int *lenp,
966b0b0382bSAl Viro 			 struct inode *parent)
967221e583aSRasmus Rohde {
968221e583aSRasmus Rohde 	int len = *lenp;
9695ca4e4beSPekka Enberg 	struct kernel_lb_addr location = UDF_I(inode)->i_location;
970221e583aSRasmus Rohde 	struct fid *fid = (struct fid *)fh;
971221e583aSRasmus Rohde 	int type = FILEID_UDF_WITHOUT_PARENT;
972221e583aSRasmus Rohde 
973b0b0382bSAl Viro 	if (parent && (len < 5)) {
9745fe0c237SAneesh Kumar K.V 		*lenp = 5;
97594e07a75SNamjae Jeon 		return FILEID_INVALID;
9765fe0c237SAneesh Kumar K.V 	} else if (len < 3) {
9775fe0c237SAneesh Kumar K.V 		*lenp = 3;
97894e07a75SNamjae Jeon 		return FILEID_INVALID;
9795fe0c237SAneesh Kumar K.V 	}
980221e583aSRasmus Rohde 
981221e583aSRasmus Rohde 	*lenp = 3;
982221e583aSRasmus Rohde 	fid->udf.block = location.logicalBlockNum;
983221e583aSRasmus Rohde 	fid->udf.partref = location.partitionReferenceNum;
9840143fc5eSMathias Krause 	fid->udf.parent_partref = 0;
985221e583aSRasmus Rohde 	fid->udf.generation = inode->i_generation;
986221e583aSRasmus Rohde 
987b0b0382bSAl Viro 	if (parent) {
988b0b0382bSAl Viro 		location = UDF_I(parent)->i_location;
989221e583aSRasmus Rohde 		fid->udf.parent_block = location.logicalBlockNum;
990221e583aSRasmus Rohde 		fid->udf.parent_partref = location.partitionReferenceNum;
991221e583aSRasmus Rohde 		fid->udf.parent_generation = inode->i_generation;
992221e583aSRasmus Rohde 		*lenp = 5;
993221e583aSRasmus Rohde 		type = FILEID_UDF_WITH_PARENT;
994221e583aSRasmus Rohde 	}
995221e583aSRasmus Rohde 
996221e583aSRasmus Rohde 	return type;
997221e583aSRasmus Rohde }
998221e583aSRasmus Rohde 
999221e583aSRasmus Rohde const struct export_operations udf_export_ops = {
1000221e583aSRasmus Rohde 	.encode_fh	= udf_encode_fh,
1001221e583aSRasmus Rohde 	.fh_to_dentry   = udf_fh_to_dentry,
1002221e583aSRasmus Rohde 	.fh_to_parent   = udf_fh_to_parent,
1003221e583aSRasmus Rohde 	.get_parent     = udf_get_parent,
1004221e583aSRasmus Rohde };
1005221e583aSRasmus Rohde 
1006c5ef1c42SArjan van de Ven const struct inode_operations udf_dir_inode_operations = {
10071da177e4SLinus Torvalds 	.lookup				= udf_lookup,
10081da177e4SLinus Torvalds 	.create				= udf_create,
10091da177e4SLinus Torvalds 	.link				= udf_link,
10101da177e4SLinus Torvalds 	.unlink				= udf_unlink,
10111da177e4SLinus Torvalds 	.symlink			= udf_symlink,
10121da177e4SLinus Torvalds 	.mkdir				= udf_mkdir,
10131da177e4SLinus Torvalds 	.rmdir				= udf_rmdir,
10141da177e4SLinus Torvalds 	.mknod				= udf_mknod,
10151da177e4SLinus Torvalds 	.rename				= udf_rename,
1016656d09dfSAl Viro 	.tmpfile			= udf_tmpfile,
10171da177e4SLinus Torvalds };
1018