ialloc.c 4.3 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
/*
 * ialloc.c
 *
 * PURPOSE
 *	Inode allocation handling routines for the OSTA-UDF(tm) filesystem.
 *
 * 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-2001 Ben Fennema
 *
 * HISTORY
 *
 *  02/24/99 blf  Created.
 *
 */

#include "udfdecl.h"
#include <linux/fs.h>
#include <linux/quotaops.h>
#include <linux/udf_fs.h>
#include <linux/sched.h>
#include <linux/slab.h>

#include "udf_i.h"
#include "udf_sb.h"

31
void udf_free_inode(struct inode *inode)
L
Linus Torvalds 已提交
32 33 34 35 36 37 38 39 40 41 42 43 44
{
	struct super_block *sb = inode->i_sb;
	struct udf_sb_info *sbi = UDF_SB(sb);

	/*
	 * Note: we must free any quota before locking the superblock,
	 * as writing the quota to disk may need the lock as well.
	 */
	DQUOT_FREE_INODE(inode);
	DQUOT_DROP(inode);

	clear_inode(inode);

I
Ingo Molnar 已提交
45
	mutex_lock(&sbi->s_alloc_mutex);
L
Linus Torvalds 已提交
46 47 48
	if (sbi->s_lvidbh) {
		if (S_ISDIR(inode->i_mode))
			UDF_SB_LVIDIU(sb)->numDirs =
49 50
			    cpu_to_le32(le32_to_cpu(UDF_SB_LVIDIU(sb)->numDirs)
					- 1);
L
Linus Torvalds 已提交
51 52
		else
			UDF_SB_LVIDIU(sb)->numFiles =
53 54
			    cpu_to_le32(le32_to_cpu(UDF_SB_LVIDIU(sb)->numFiles)
					- 1);
55

L
Linus Torvalds 已提交
56 57
		mark_buffer_dirty(sbi->s_lvidbh);
	}
I
Ingo Molnar 已提交
58
	mutex_unlock(&sbi->s_alloc_mutex);
L
Linus Torvalds 已提交
59 60 61 62

	udf_free_blocks(sb, NULL, UDF_I_LOCATION(inode), 0, 1);
}

63
struct inode *udf_new_inode(struct inode *dir, int mode, int *err)
L
Linus Torvalds 已提交
64 65 66
{
	struct super_block *sb = dir->i_sb;
	struct udf_sb_info *sbi = UDF_SB(sb);
67
	struct inode *inode;
L
Linus Torvalds 已提交
68 69 70 71 72
	int block;
	uint32_t start = UDF_I_LOCATION(dir).logicalBlockNum;

	inode = new_inode(sb);

73
	if (!inode) {
L
Linus Torvalds 已提交
74 75 76 77 78
		*err = -ENOMEM;
		return NULL;
	}
	*err = -ENOSPC;

79 80 81 82 83 84
	UDF_I_UNIQUE(inode) = 0;
	UDF_I_LENEXTENTS(inode) = 0;
	UDF_I_NEXT_ALLOC_BLOCK(inode) = 0;
	UDF_I_NEXT_ALLOC_GOAL(inode) = 0;
	UDF_I_STRAT4096(inode) = 0;

85 86 87 88 89
	block =
	    udf_new_block(dir->i_sb, NULL,
			  UDF_I_LOCATION(dir).partitionReferenceNum, start,
			  err);
	if (*err) {
L
Linus Torvalds 已提交
90 91 92 93
		iput(inode);
		return NULL;
	}

I
Ingo Molnar 已提交
94
	mutex_lock(&sbi->s_alloc_mutex);
95
	if (UDF_SB_LVIDBH(sb)) {
L
Linus Torvalds 已提交
96 97
		struct logicalVolHeaderDesc *lvhd;
		uint64_t uniqueID;
98 99 100
		lvhd =
		    (struct logicalVolHeaderDesc *)(UDF_SB_LVID(sb)->
						    logicalVolContentsUse);
L
Linus Torvalds 已提交
101 102
		if (S_ISDIR(mode))
			UDF_SB_LVIDIU(sb)->numDirs =
103 104
			    cpu_to_le32(le32_to_cpu(UDF_SB_LVIDIU(sb)->numDirs)
					+ 1);
L
Linus Torvalds 已提交
105 106
		else
			UDF_SB_LVIDIU(sb)->numFiles =
107 108
			    cpu_to_le32(le32_to_cpu(UDF_SB_LVIDIU(sb)->numFiles)
					+ 1);
L
Linus Torvalds 已提交
109 110 111 112 113 114 115 116
		UDF_I_UNIQUE(inode) = uniqueID = le64_to_cpu(lvhd->uniqueID);
		if (!(++uniqueID & 0x00000000FFFFFFFFUL))
			uniqueID += 16;
		lvhd->uniqueID = cpu_to_le64(uniqueID);
		mark_buffer_dirty(UDF_SB_LVIDBH(sb));
	}
	inode->i_mode = mode;
	inode->i_uid = current->fsuid;
117
	if (dir->i_mode & S_ISGID) {
L
Linus Torvalds 已提交
118 119 120
		inode->i_gid = dir->i_gid;
		if (S_ISDIR(mode))
			mode |= S_ISGID;
121
	} else
L
Linus Torvalds 已提交
122 123 124
		inode->i_gid = current->fsgid;

	UDF_I_LOCATION(inode).logicalBlockNum = block;
125 126
	UDF_I_LOCATION(inode).partitionReferenceNum =
	    UDF_I_LOCATION(dir).partitionReferenceNum;
L
Linus Torvalds 已提交
127 128 129 130 131
	inode->i_ino = udf_get_lb_pblock(sb, UDF_I_LOCATION(inode), 0);
	inode->i_blocks = 0;
	UDF_I_LENEATTR(inode) = 0;
	UDF_I_LENALLOC(inode) = 0;
	UDF_I_USE(inode) = 0;
132
	if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_EXTENDED_FE)) {
L
Linus Torvalds 已提交
133 134
		UDF_I_EFE(inode) = 1;
		UDF_UPDATE_UDFREV(inode->i_sb, UDF_VERS_USE_EXTENDED_FE);
135 136 137 138
		UDF_I_DATA(inode) =
		    kzalloc(inode->i_sb->s_blocksize -
			    sizeof(struct extendedFileEntry), GFP_KERNEL);
	} else {
L
Linus Torvalds 已提交
139
		UDF_I_EFE(inode) = 0;
140 141 142
		UDF_I_DATA(inode) =
		    kzalloc(inode->i_sb->s_blocksize - sizeof(struct fileEntry),
			    GFP_KERNEL);
L
Linus Torvalds 已提交
143
	}
144
	if (!UDF_I_DATA(inode)) {
145 146 147 148 149
		iput(inode);
		*err = -ENOMEM;
		mutex_unlock(&sbi->s_alloc_mutex);
		return NULL;
	}
L
Linus Torvalds 已提交
150 151 152 153 154 155 156
	if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_AD_IN_ICB))
		UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_IN_ICB;
	else if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
		UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_SHORT;
	else
		UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_LONG;
	inode->i_mtime = inode->i_atime = inode->i_ctime =
157
	    UDF_I_CRTIME(inode) = current_fs_time(inode->i_sb);
L
Linus Torvalds 已提交
158 159
	insert_inode_hash(inode);
	mark_inode_dirty(inode);
I
Ingo Molnar 已提交
160
	mutex_unlock(&sbi->s_alloc_mutex);
L
Linus Torvalds 已提交
161

162
	if (DQUOT_ALLOC_INODE(inode)) {
L
Linus Torvalds 已提交
163 164 165 166 167 168 169 170 171 172 173
		DQUOT_DROP(inode);
		inode->i_flags |= S_NOQUOTA;
		inode->i_nlink = 0;
		iput(inode);
		*err = -EDQUOT;
		return NULL;
	}

	*err = 0;
	return inode;
}