⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 inode.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* stat data of object has been inserted, this inserts the item   containing the body of symlink */static int reiserfs_new_symlink(struct reiserfs_transaction_handle *th, struct inode *inode,	/* Inode of symlink */				struct item_head *ih,				struct treepath *path, const char *symname,				int item_len){	struct super_block *sb = th->t_super;	struct cpu_key key;	int retval;	BUG_ON(!th->t_trans_id);	_make_cpu_key(&key, KEY_FORMAT_3_5,		      le32_to_cpu(ih->ih_key.k_dir_id),		      le32_to_cpu(ih->ih_key.k_objectid),		      1, TYPE_DIRECT, 3 /*key length */ );	make_le_item_head(ih, NULL, KEY_FORMAT_3_5, 1, TYPE_DIRECT, item_len,			  0 /*free_space */ );	/* look for place in the tree for new item */	retval = search_item(sb, &key, path);	if (retval == IO_ERROR) {		reiserfs_warning(sb, "vs-13080: reiserfs_new_symlinik: "				 "i/o failure occurred creating new symlink");		return -EIO;	}	if (retval == ITEM_FOUND) {		pathrelse(path);		reiserfs_warning(sb, "vs-13080: reiserfs_new_symlink: "				 "object with this key exists (%k)",				 &(ih->ih_key));		return -EEXIST;	}	/* insert item, that is body of symlink */	return reiserfs_insert_item(th, path, &key, ih, inode, symname);}/* inserts the stat data into the tree, and then calls   reiserfs_new_directory (to insert ".", ".." item if new object is   directory) or reiserfs_new_symlink (to insert symlink body if new   object is symlink) or nothing (if new object is regular file)    NOTE! uid and gid must already be set in the inode.  If we return   non-zero due to an error, we have to drop the quota previously allocated   for the fresh inode.  This can only be done outside a transaction, so   if we return non-zero, we also end the transaction.  */int reiserfs_new_inode(struct reiserfs_transaction_handle *th,		       struct inode *dir, int mode, const char *symname,		       /* 0 for regular, EMTRY_DIR_SIZE for dirs, 		          strlen (symname) for symlinks) */		       loff_t i_size, struct dentry *dentry,		       struct inode *inode){	struct super_block *sb;	INITIALIZE_PATH(path_to_key);	struct cpu_key key;	struct item_head ih;	struct stat_data sd;	int retval;	int err;	BUG_ON(!th->t_trans_id);	if (DQUOT_ALLOC_INODE(inode)) {		err = -EDQUOT;		goto out_end_trans;	}	if (!dir->i_nlink) {		err = -EPERM;		goto out_bad_inode;	}	sb = dir->i_sb;	/* item head of new item */	ih.ih_key.k_dir_id = reiserfs_choose_packing(dir);	ih.ih_key.k_objectid = cpu_to_le32(reiserfs_get_unused_objectid(th));	if (!ih.ih_key.k_objectid) {		err = -ENOMEM;		goto out_bad_inode;	}	if (old_format_only(sb))		/* not a perfect generation count, as object ids can be reused, but 		 ** this is as good as reiserfs can do right now.		 ** note that the private part of inode isn't filled in yet, we have		 ** to use the directory.		 */		inode->i_generation = le32_to_cpu(INODE_PKEY(dir)->k_objectid);	else#if defined( USE_INODE_GENERATION_COUNTER )		inode->i_generation =		    le32_to_cpu(REISERFS_SB(sb)->s_rs->s_inode_generation);#else		inode->i_generation = ++event;#endif	/* fill stat data */	inode->i_nlink = (S_ISDIR(mode) ? 2 : 1);	/* uid and gid must already be set by the caller for quota init */	/* symlink cannot be immutable or append only, right? */	if (S_ISLNK(inode->i_mode))		inode->i_flags &= ~(S_IMMUTABLE | S_APPEND);	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;	inode->i_size = i_size;	inode->i_blocks = 0;	inode->i_bytes = 0;	REISERFS_I(inode)->i_first_direct_byte = S_ISLNK(mode) ? 1 :	    U32_MAX /*NO_BYTES_IN_DIRECT_ITEM */ ;	INIT_LIST_HEAD(&(REISERFS_I(inode)->i_prealloc_list));	REISERFS_I(inode)->i_flags = 0;	REISERFS_I(inode)->i_prealloc_block = 0;	REISERFS_I(inode)->i_prealloc_count = 0;	REISERFS_I(inode)->i_trans_id = 0;	REISERFS_I(inode)->i_jl = NULL;	REISERFS_I(inode)->i_attrs =	    REISERFS_I(dir)->i_attrs & REISERFS_INHERIT_MASK;	sd_attrs_to_i_attrs(REISERFS_I(inode)->i_attrs, inode);	mutex_init(&(REISERFS_I(inode)->i_mmap));	reiserfs_init_acl_access(inode);	reiserfs_init_acl_default(inode);	reiserfs_init_xattr_rwsem(inode);	if (old_format_only(sb))		make_le_item_head(&ih, NULL, KEY_FORMAT_3_5, SD_OFFSET,				  TYPE_STAT_DATA, SD_V1_SIZE, MAX_US_INT);	else		make_le_item_head(&ih, NULL, KEY_FORMAT_3_6, SD_OFFSET,				  TYPE_STAT_DATA, SD_SIZE, MAX_US_INT);	/* key to search for correct place for new stat data */	_make_cpu_key(&key, KEY_FORMAT_3_6, le32_to_cpu(ih.ih_key.k_dir_id),		      le32_to_cpu(ih.ih_key.k_objectid), SD_OFFSET,		      TYPE_STAT_DATA, 3 /*key length */ );	/* find proper place for inserting of stat data */	retval = search_item(sb, &key, &path_to_key);	if (retval == IO_ERROR) {		err = -EIO;		goto out_bad_inode;	}	if (retval == ITEM_FOUND) {		pathrelse(&path_to_key);		err = -EEXIST;		goto out_bad_inode;	}	if (old_format_only(sb)) {		if (inode->i_uid & ~0xffff || inode->i_gid & ~0xffff) {			pathrelse(&path_to_key);			/* i_uid or i_gid is too big to be stored in stat data v3.5 */			err = -EINVAL;			goto out_bad_inode;		}		inode2sd_v1(&sd, inode, inode->i_size);	} else {		inode2sd(&sd, inode, inode->i_size);	}	// these do not go to on-disk stat data	inode->i_ino = le32_to_cpu(ih.ih_key.k_objectid);	// store in in-core inode the key of stat data and version all	// object items will have (directory items will have old offset	// format, other new objects will consist of new items)	memcpy(INODE_PKEY(inode), &(ih.ih_key), KEY_SIZE);	if (old_format_only(sb) || S_ISDIR(mode) || S_ISLNK(mode))		set_inode_item_key_version(inode, KEY_FORMAT_3_5);	else		set_inode_item_key_version(inode, KEY_FORMAT_3_6);	if (old_format_only(sb))		set_inode_sd_version(inode, STAT_DATA_V1);	else		set_inode_sd_version(inode, STAT_DATA_V2);	/* insert the stat data into the tree */#ifdef DISPLACE_NEW_PACKING_LOCALITIES	if (REISERFS_I(dir)->new_packing_locality)		th->displace_new_blocks = 1;#endif	retval =	    reiserfs_insert_item(th, &path_to_key, &key, &ih, inode,				 (char *)(&sd));	if (retval) {		err = retval;		reiserfs_check_path(&path_to_key);		goto out_bad_inode;	}#ifdef DISPLACE_NEW_PACKING_LOCALITIES	if (!th->displace_new_blocks)		REISERFS_I(dir)->new_packing_locality = 0;#endif	if (S_ISDIR(mode)) {		/* insert item with "." and ".." */		retval =		    reiserfs_new_directory(th, inode, &ih, &path_to_key, dir);	}	if (S_ISLNK(mode)) {		/* insert body of symlink */		if (!old_format_only(sb))			i_size = ROUND_UP(i_size);		retval =		    reiserfs_new_symlink(th, inode, &ih, &path_to_key, symname,					 i_size);	}	if (retval) {		err = retval;		reiserfs_check_path(&path_to_key);		journal_end(th, th->t_super, th->t_blocks_allocated);		goto out_inserted_sd;	}	/* XXX CHECK THIS */	if (reiserfs_posixacl(inode->i_sb)) {		retval = reiserfs_inherit_default_acl(dir, dentry, inode);		if (retval) {			err = retval;			reiserfs_check_path(&path_to_key);			journal_end(th, th->t_super, th->t_blocks_allocated);			goto out_inserted_sd;		}	} else if (inode->i_sb->s_flags & MS_POSIXACL) {		reiserfs_warning(inode->i_sb, "ACLs aren't enabled in the fs, "				 "but vfs thinks they are!");	} else if (is_reiserfs_priv_object(dir)) {		reiserfs_mark_inode_private(inode);	}	insert_inode_hash(inode);	reiserfs_update_sd(th, inode);	reiserfs_check_path(&path_to_key);	return 0;/* it looks like you can easily compress these two goto targets into * one.  Keeping it like this doesn't actually hurt anything, and they * are place holders for what the quota code actually needs. */      out_bad_inode:	/* Invalidate the object, nothing was inserted yet */	INODE_PKEY(inode)->k_objectid = 0;	/* Quota change must be inside a transaction for journaling */	DQUOT_FREE_INODE(inode);      out_end_trans:	journal_end(th, th->t_super, th->t_blocks_allocated);	/* Drop can be outside and it needs more credits so it's better to have it outside */	DQUOT_DROP(inode);	inode->i_flags |= S_NOQUOTA;	make_bad_inode(inode);      out_inserted_sd:	inode->i_nlink = 0;	th->t_trans_id = 0;	/* so the caller can't use this handle later */	/* If we were inheriting an ACL, we need to release the lock so that	 * iput doesn't deadlock in reiserfs_delete_xattrs. The locking	 * code really needs to be reworked, but this will take care of it	 * for now. -jeffm */#ifdef CONFIG_REISERFS_FS_POSIX_ACL	if (REISERFS_I(dir)->i_acl_default && !IS_ERR(REISERFS_I(dir)->i_acl_default)) {		reiserfs_write_unlock_xattrs(dir->i_sb);		iput(inode);		reiserfs_write_lock_xattrs(dir->i_sb);	} else#endif		iput(inode);	return err;}/*** finds the tail page in the page cache,** reads the last block in.**** On success, page_result is set to a locked, pinned page, and bh_result** is set to an up to date buffer for the last block in the file.  returns 0.**** tail conversion is not done, so bh_result might not be valid for writing** check buffer_mapped(bh_result) and bh_result->b_blocknr != 0 before** trying to write the block.**** on failure, nonzero is returned, page_result and bh_result are untouched.*/static int grab_tail_page(struct inode *p_s_inode,			  struct page **page_result,			  struct buffer_head **bh_result){	/* we want the page with the last byte in the file,	 ** not the page that will hold the next byte for appending	 */	unsigned long index = (p_s_inode->i_size - 1) >> PAGE_CACHE_SHIFT;	unsigned long pos = 0;	unsigned long start = 0;	unsigned long blocksize = p_s_inode->i_sb->s_blocksize;	unsigned long offset = (p_s_inode->i_size) & (PAGE_CACHE_SIZE - 1);	struct buffer_head *bh;	struct buffer_head *head;	struct page *page;	int error;	/* we know that we are only called with inode->i_size > 0.	 ** we also know that a file tail can never be as big as a block	 ** If i_size % blocksize == 0, our file is currently block aligned	 ** and it won't need converting or zeroing after a truncate.	 */	if ((offset & (blocksize - 1)) == 0) {		return -ENOENT;	}	page = grab_cache_page(p_s_inode->i_mapping, index);	error = -ENOMEM;	if (!page) {		goto out;	}	/* start within the page of the last block in the file */	start = (offset / blocksize) * blocksize;	error = block_prepare_write(page, start, offset,				    reiserfs_get_block_create_0);	if (error)		goto unlock;	head = page_buffers(page);	bh = head;	do {		if (pos >= start) {			break;		}		bh = bh->b_this_page;		pos += blocksize;	} while (bh != head);	if (!buffer_uptodate(bh)) {		/* note, this should never happen, prepare_write should		 ** be taking care of this for us.  If the buffer isn't up to date,		 ** I've screwed up the code to find the buffer, or the code to		 ** call prepare_write		 */		reiserfs_warning(p_s_inode->i_sb,				 "clm-6000: error reading block %lu on dev %s",				 bh->b_blocknr,				 reiserfs_bdevname(p_s_inode->i_sb));		error = -EIO;		goto unlock;	}	*bh_result = bh;	*page_result = page;      out:	return error;      unlock:	unlock_page(page);	page_cache_release(page);	return error;}/*** vfs version of truncate file.  Must NOT be called with** a transaction already started.**** some code taken from block_truncate_page*/int reiserfs_truncate_file(struct inode *p_s_inode, int update_timestamps){	struct reiserfs_transaction_handle th;	/* we want the offset for the first byte after the end of the file */	unsigned long offset = p_s_inode->i_size & (PAGE_CACHE_SIZE - 1);	unsigned blocksize = p_s_inode->i_sb->s_blocksize;	unsigned length;	struct page *page = NULL;	int error;	struct buffer_head *bh = NULL;	int err2;	reiserfs_write_lock(p_s_inode->i_sb);	if (p_s_inode->i_size > 0) {		if ((error = grab_tail_page(p_s_inode, &page, &bh))) {			// -ENOENT means we truncated past the end of the file, 			// and get_block_create_0 could not find a block to read in,			// which is ok.			if (error != -ENOENT)				reiserfs_warning(p_s_inode->i_sb,						 "clm-6001: grab_tail_page failed %d",						 error);			page = NULL;			bh = NULL;		}	}	/* so, if page != NULL, we have a buffer head for the offset at 	 ** the end of the file. if the bh is mapped, and bh->b_blocknr != 0, 	 ** then we have an unformatted node.  Otherwise, we have a direct item, 	 ** and no zeroing is required on disk.  We zero after the truncate, 	 ** because the truncate might pack the item anyway 	 ** (it will unmap bh if it packs).	 */	/* it is enough to reserve space in transaction for 2 balancings:	   one for "save" link adding and another for the first	   cut_from_item. 1 is for update_sd */	error = journal_begin(&th, p_s_inode->i_sb,			      JOURNAL_PER_BALANCE_CNT * 2 + 1);	if (error)		goto out;	reiserfs_update_inode_transaction(p_s_inode);	if (update_timestamps)		/* we are doing real truncate: if the system crashes before the last		   transaction of truncating gets committed - on reboot the file		   either appears truncated properly or not truncated at all */		add_save_link(&th, p_s_inode, 1);	err2 = reiserfs_do_truncate(&th, p_s_inode, page, update_timestamps);	error =	    journal_end(&th, p_s_inode->i_sb, JOURNAL_PER_BALANCE_CNT * 2 + 1);	if (error)		goto out

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -