xref: /kernel/linux/linux-5.10/fs/udf/ialloc.c (revision 8c2ecf20)
18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * ialloc.c
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * PURPOSE
58c2ecf20Sopenharmony_ci *	Inode allocation handling routines for the OSTA-UDF(tm) filesystem.
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci * COPYRIGHT
88c2ecf20Sopenharmony_ci *	This file is distributed under the terms of the GNU General Public
98c2ecf20Sopenharmony_ci *	License (GPL). Copies of the GPL can be obtained from:
108c2ecf20Sopenharmony_ci *		ftp://prep.ai.mit.edu/pub/gnu/GPL
118c2ecf20Sopenharmony_ci *	Each contributing author retains all rights to their own work.
128c2ecf20Sopenharmony_ci *
138c2ecf20Sopenharmony_ci *  (C) 1998-2001 Ben Fennema
148c2ecf20Sopenharmony_ci *
158c2ecf20Sopenharmony_ci * HISTORY
168c2ecf20Sopenharmony_ci *
178c2ecf20Sopenharmony_ci *  02/24/99 blf  Created.
188c2ecf20Sopenharmony_ci *
198c2ecf20Sopenharmony_ci */
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ci#include "udfdecl.h"
228c2ecf20Sopenharmony_ci#include <linux/fs.h>
238c2ecf20Sopenharmony_ci#include <linux/sched.h>
248c2ecf20Sopenharmony_ci#include <linux/slab.h>
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci#include "udf_i.h"
278c2ecf20Sopenharmony_ci#include "udf_sb.h"
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_civoid udf_free_inode(struct inode *inode)
308c2ecf20Sopenharmony_ci{
318c2ecf20Sopenharmony_ci	struct super_block *sb = inode->i_sb;
328c2ecf20Sopenharmony_ci	struct udf_sb_info *sbi = UDF_SB(sb);
338c2ecf20Sopenharmony_ci	struct logicalVolIntegrityDescImpUse *lvidiu = udf_sb_lvidiu(sb);
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci	if (lvidiu) {
368c2ecf20Sopenharmony_ci		mutex_lock(&sbi->s_alloc_mutex);
378c2ecf20Sopenharmony_ci		if (S_ISDIR(inode->i_mode))
388c2ecf20Sopenharmony_ci			le32_add_cpu(&lvidiu->numDirs, -1);
398c2ecf20Sopenharmony_ci		else
408c2ecf20Sopenharmony_ci			le32_add_cpu(&lvidiu->numFiles, -1);
418c2ecf20Sopenharmony_ci		udf_updated_lvid(sb);
428c2ecf20Sopenharmony_ci		mutex_unlock(&sbi->s_alloc_mutex);
438c2ecf20Sopenharmony_ci	}
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ci	udf_free_blocks(sb, NULL, &UDF_I(inode)->i_location, 0, 1);
468c2ecf20Sopenharmony_ci}
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_cistruct inode *udf_new_inode(struct inode *dir, umode_t mode)
498c2ecf20Sopenharmony_ci{
508c2ecf20Sopenharmony_ci	struct super_block *sb = dir->i_sb;
518c2ecf20Sopenharmony_ci	struct udf_sb_info *sbi = UDF_SB(sb);
528c2ecf20Sopenharmony_ci	struct inode *inode;
538c2ecf20Sopenharmony_ci	udf_pblk_t block;
548c2ecf20Sopenharmony_ci	uint32_t start = UDF_I(dir)->i_location.logicalBlockNum;
558c2ecf20Sopenharmony_ci	struct udf_inode_info *iinfo;
568c2ecf20Sopenharmony_ci	struct udf_inode_info *dinfo = UDF_I(dir);
578c2ecf20Sopenharmony_ci	struct logicalVolIntegrityDescImpUse *lvidiu;
588c2ecf20Sopenharmony_ci	int err;
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_ci	inode = new_inode(sb);
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ci	if (!inode)
638c2ecf20Sopenharmony_ci		return ERR_PTR(-ENOMEM);
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_ci	iinfo = UDF_I(inode);
668c2ecf20Sopenharmony_ci	if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_EXTENDED_FE)) {
678c2ecf20Sopenharmony_ci		iinfo->i_efe = 1;
688c2ecf20Sopenharmony_ci		if (UDF_VERS_USE_EXTENDED_FE > sbi->s_udfrev)
698c2ecf20Sopenharmony_ci			sbi->s_udfrev = UDF_VERS_USE_EXTENDED_FE;
708c2ecf20Sopenharmony_ci		iinfo->i_data = kzalloc(inode->i_sb->s_blocksize -
718c2ecf20Sopenharmony_ci					sizeof(struct extendedFileEntry),
728c2ecf20Sopenharmony_ci					GFP_KERNEL);
738c2ecf20Sopenharmony_ci	} else {
748c2ecf20Sopenharmony_ci		iinfo->i_efe = 0;
758c2ecf20Sopenharmony_ci		iinfo->i_data = kzalloc(inode->i_sb->s_blocksize -
768c2ecf20Sopenharmony_ci					sizeof(struct fileEntry),
778c2ecf20Sopenharmony_ci					GFP_KERNEL);
788c2ecf20Sopenharmony_ci	}
798c2ecf20Sopenharmony_ci	if (!iinfo->i_data) {
808c2ecf20Sopenharmony_ci		make_bad_inode(inode);
818c2ecf20Sopenharmony_ci		iput(inode);
828c2ecf20Sopenharmony_ci		return ERR_PTR(-ENOMEM);
838c2ecf20Sopenharmony_ci	}
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_ci	err = -ENOSPC;
868c2ecf20Sopenharmony_ci	block = udf_new_block(dir->i_sb, NULL,
878c2ecf20Sopenharmony_ci			      dinfo->i_location.partitionReferenceNum,
888c2ecf20Sopenharmony_ci			      start, &err);
898c2ecf20Sopenharmony_ci	if (err) {
908c2ecf20Sopenharmony_ci		make_bad_inode(inode);
918c2ecf20Sopenharmony_ci		iput(inode);
928c2ecf20Sopenharmony_ci		return ERR_PTR(err);
938c2ecf20Sopenharmony_ci	}
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ci	lvidiu = udf_sb_lvidiu(sb);
968c2ecf20Sopenharmony_ci	if (lvidiu) {
978c2ecf20Sopenharmony_ci		iinfo->i_unique = lvid_get_unique_id(sb);
988c2ecf20Sopenharmony_ci		inode->i_generation = iinfo->i_unique;
998c2ecf20Sopenharmony_ci		mutex_lock(&sbi->s_alloc_mutex);
1008c2ecf20Sopenharmony_ci		if (S_ISDIR(mode))
1018c2ecf20Sopenharmony_ci			le32_add_cpu(&lvidiu->numDirs, 1);
1028c2ecf20Sopenharmony_ci		else
1038c2ecf20Sopenharmony_ci			le32_add_cpu(&lvidiu->numFiles, 1);
1048c2ecf20Sopenharmony_ci		udf_updated_lvid(sb);
1058c2ecf20Sopenharmony_ci		mutex_unlock(&sbi->s_alloc_mutex);
1068c2ecf20Sopenharmony_ci	}
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_ci	inode_init_owner(inode, dir, mode);
1098c2ecf20Sopenharmony_ci	if (UDF_QUERY_FLAG(sb, UDF_FLAG_UID_SET))
1108c2ecf20Sopenharmony_ci		inode->i_uid = sbi->s_uid;
1118c2ecf20Sopenharmony_ci	if (UDF_QUERY_FLAG(sb, UDF_FLAG_GID_SET))
1128c2ecf20Sopenharmony_ci		inode->i_gid = sbi->s_gid;
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_ci	iinfo->i_location.logicalBlockNum = block;
1158c2ecf20Sopenharmony_ci	iinfo->i_location.partitionReferenceNum =
1168c2ecf20Sopenharmony_ci				dinfo->i_location.partitionReferenceNum;
1178c2ecf20Sopenharmony_ci	inode->i_ino = udf_get_lb_pblock(sb, &iinfo->i_location, 0);
1188c2ecf20Sopenharmony_ci	inode->i_blocks = 0;
1198c2ecf20Sopenharmony_ci	iinfo->i_lenEAttr = 0;
1208c2ecf20Sopenharmony_ci	iinfo->i_lenAlloc = 0;
1218c2ecf20Sopenharmony_ci	iinfo->i_use = 0;
1228c2ecf20Sopenharmony_ci	iinfo->i_checkpoint = 1;
1238c2ecf20Sopenharmony_ci	iinfo->i_extraPerms = FE_PERM_U_CHATTR;
1248c2ecf20Sopenharmony_ci	udf_update_extra_perms(inode, mode);
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_ci	if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_AD_IN_ICB))
1278c2ecf20Sopenharmony_ci		iinfo->i_alloc_type = ICBTAG_FLAG_AD_IN_ICB;
1288c2ecf20Sopenharmony_ci	else if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
1298c2ecf20Sopenharmony_ci		iinfo->i_alloc_type = ICBTAG_FLAG_AD_SHORT;
1308c2ecf20Sopenharmony_ci	else
1318c2ecf20Sopenharmony_ci		iinfo->i_alloc_type = ICBTAG_FLAG_AD_LONG;
1328c2ecf20Sopenharmony_ci	inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
1338c2ecf20Sopenharmony_ci	iinfo->i_crtime = inode->i_mtime;
1348c2ecf20Sopenharmony_ci	if (unlikely(insert_inode_locked(inode) < 0)) {
1358c2ecf20Sopenharmony_ci		make_bad_inode(inode);
1368c2ecf20Sopenharmony_ci		iput(inode);
1378c2ecf20Sopenharmony_ci		return ERR_PTR(-EIO);
1388c2ecf20Sopenharmony_ci	}
1398c2ecf20Sopenharmony_ci	mark_inode_dirty(inode);
1408c2ecf20Sopenharmony_ci
1418c2ecf20Sopenharmony_ci	return inode;
1428c2ecf20Sopenharmony_ci}
143