linux/fs/ocfs2/namei.c

// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * namei.c
 *
 * Create and rename file, directory, symlinks
 *
 * Copyright (C) 2002, 2004 Oracle.  All rights reserved.
 *
 *  Portions of this code from linux/fs/ext3/dir.c
 *
 *  Copyright (C) 1992, 1993, 1994, 1995
 *  Remy Card ([email protected])
 *  Laboratoire MASI - Institut Blaise pascal
 *  Universite Pierre et Marie Curie (Paris VI)
 *
 *   from
 *
 *   linux/fs/minix/dir.c
 *
 *   Copyright (C) 1991, 1992 Linux Torvalds
 */

#include <linux/fs.h>
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/highmem.h>
#include <linux/quotaops.h>
#include <linux/iversion.h>

#include <cluster/masklog.h>

#include "ocfs2.h"

#include "alloc.h"
#include "dcache.h"
#include "dir.h"
#include "dlmglue.h"
#include "extent_map.h"
#include "file.h"
#include "inode.h"
#include "journal.h"
#include "namei.h"
#include "suballoc.h"
#include "super.h"
#include "symlink.h"
#include "sysfile.h"
#include "uptodate.h"
#include "xattr.h"
#include "acl.h"
#include "ocfs2_trace.h"
#include "ioctl.h"

#include "buffer_head_io.h"

static int ocfs2_mknod_locked(struct ocfs2_super *osb,
			      struct inode *dir,
			      struct inode *inode,
			      dev_t dev,
			      struct buffer_head **new_fe_bh,
			      struct buffer_head *parent_fe_bh,
			      handle_t *handle,
			      struct ocfs2_alloc_context *inode_ac);

static int ocfs2_prepare_orphan_dir(struct ocfs2_super *osb,
				    struct inode **ret_orphan_dir,
				    u64 blkno,
				    char *name,
				    struct ocfs2_dir_lookup_result *lookup,
				    bool dio);

static int ocfs2_orphan_add(struct ocfs2_super *osb,
			    handle_t *handle,
			    struct inode *inode,
			    struct buffer_head *fe_bh,
			    char *name,
			    struct ocfs2_dir_lookup_result *lookup,
			    struct inode *orphan_dir_inode,
			    bool dio);

static int ocfs2_create_symlink_data(struct ocfs2_super *osb,
				     handle_t *handle,
				     struct inode *inode,
				     const char *symname);

static int ocfs2_double_lock(struct ocfs2_super *osb,
			     struct buffer_head **bh1,
			     struct inode *inode1,
			     struct buffer_head **bh2,
			     struct inode *inode2,
			     int rename);

static void ocfs2_double_unlock(struct inode *inode1, struct inode *inode2);
/* An orphan dir name is an 8 byte value, printed as a hex string */
#define OCFS2_ORPHAN_NAMELEN

static struct dentry *ocfs2_lookup(struct inode *dir, struct dentry *dentry,
				   unsigned int flags)
{}

static struct inode *ocfs2_get_init_inode(struct inode *dir, umode_t mode)
{}

static void ocfs2_cleanup_add_entry_failure(struct ocfs2_super *osb,
		struct dentry *dentry, struct inode *inode)
{}

static int ocfs2_mknod(struct mnt_idmap *idmap,
		       struct inode *dir,
		       struct dentry *dentry,
		       umode_t mode,
		       dev_t dev)
{}

static int __ocfs2_mknod_locked(struct inode *dir,
				struct inode *inode,
				dev_t dev,
				struct buffer_head **new_fe_bh,
				struct buffer_head *parent_fe_bh,
				handle_t *handle,
				struct ocfs2_alloc_context *inode_ac,
				u64 fe_blkno, u64 suballoc_loc, u16 suballoc_bit)
{}

static int ocfs2_mknod_locked(struct ocfs2_super *osb,
			      struct inode *dir,
			      struct inode *inode,
			      dev_t dev,
			      struct buffer_head **new_fe_bh,
			      struct buffer_head *parent_fe_bh,
			      handle_t *handle,
			      struct ocfs2_alloc_context *inode_ac)
{}

static int ocfs2_mkdir(struct mnt_idmap *idmap,
		       struct inode *dir,
		       struct dentry *dentry,
		       umode_t mode)
{}

static int ocfs2_create(struct mnt_idmap *idmap,
			struct inode *dir,
			struct dentry *dentry,
			umode_t mode,
			bool excl)
{}

static int ocfs2_link(struct dentry *old_dentry,
		      struct inode *dir,
		      struct dentry *dentry)
{}

/*
 * Takes and drops an exclusive lock on the given dentry. This will
 * force other nodes to drop it.
 */
static int ocfs2_remote_dentry_delete(struct dentry *dentry)
{}

static inline int ocfs2_inode_is_unlinkable(struct inode *inode)
{}

static int ocfs2_unlink(struct inode *dir,
			struct dentry *dentry)
{}

static int ocfs2_check_if_ancestor(struct ocfs2_super *osb,
		u64 src_inode_no, u64 dest_inode_no)
{}

/*
 * The only place this should be used is rename and link!
 * if they have the same id, then the 1st one is the only one locked.
 */
static int ocfs2_double_lock(struct ocfs2_super *osb,
			     struct buffer_head **bh1,
			     struct inode *inode1,
			     struct buffer_head **bh2,
			     struct inode *inode2,
			     int rename)
{}

static void ocfs2_double_unlock(struct inode *inode1, struct inode *inode2)
{}

static int ocfs2_rename(struct mnt_idmap *idmap,
			struct inode *old_dir,
			struct dentry *old_dentry,
			struct inode *new_dir,
			struct dentry *new_dentry,
			unsigned int flags)
{}

/*
 * we expect i_size = strlen(symname). Copy symname into the file
 * data, including the null terminator.
 */
static int ocfs2_create_symlink_data(struct ocfs2_super *osb,
				     handle_t *handle,
				     struct inode *inode,
				     const char *symname)
{}

static int ocfs2_symlink(struct mnt_idmap *idmap,
			 struct inode *dir,
			 struct dentry *dentry,
			 const char *symname)
{}

static int ocfs2_blkno_stringify(u64 blkno, char *name)
{}

static int ocfs2_lookup_lock_orphan_dir(struct ocfs2_super *osb,
					struct inode **ret_orphan_dir,
					struct buffer_head **ret_orphan_dir_bh)
{}

static int __ocfs2_prepare_orphan_dir(struct inode *orphan_dir_inode,
				      struct buffer_head *orphan_dir_bh,
				      u64 blkno,
				      char *name,
				      struct ocfs2_dir_lookup_result *lookup,
				      bool dio)
{}

/**
 * ocfs2_prepare_orphan_dir() - Prepare an orphan directory for
 * insertion of an orphan.
 * @osb: ocfs2 file system
 * @ret_orphan_dir: Orphan dir inode - returned locked!
 * @blkno: Actual block number of the inode to be inserted into orphan dir.
 * @name: Buffer to store the name of the orphan.
 * @lookup: dir lookup result, to be passed back into functions like
 *          ocfs2_orphan_add
 * @dio: Flag indicating if direct IO is being used or not.
 *
 * Returns zero on success and the ret_orphan_dir, name and lookup
 * fields will be populated.
 *
 * Returns non-zero on failure. 
 */
static int ocfs2_prepare_orphan_dir(struct ocfs2_super *osb,
				    struct inode **ret_orphan_dir,
				    u64 blkno,
				    char *name,
				    struct ocfs2_dir_lookup_result *lookup,
				    bool dio)
{}

static int ocfs2_orphan_add(struct ocfs2_super *osb,
			    handle_t *handle,
			    struct inode *inode,
			    struct buffer_head *fe_bh,
			    char *name,
			    struct ocfs2_dir_lookup_result *lookup,
			    struct inode *orphan_dir_inode,
			    bool dio)
{}

/* unlike orphan_add, we expect the orphan dir to already be locked here. */
int ocfs2_orphan_del(struct ocfs2_super *osb,
		     handle_t *handle,
		     struct inode *orphan_dir_inode,
		     struct inode *inode,
		     struct buffer_head *orphan_dir_bh,
		     bool dio)
{}

/**
 * ocfs2_prep_new_orphaned_file() - Prepare the orphan dir to receive a newly
 * allocated file. This is different from the typical 'add to orphan dir'
 * operation in that the inode does not yet exist. This is a problem because
 * the orphan dir stringifies the inode block number to come up with it's
 * dirent. Obviously if the inode does not yet exist we have a chicken and egg
 * problem. This function works around it by calling deeper into the orphan
 * and suballoc code than other callers. Use this only by necessity.
 * @dir: The directory which this inode will ultimately wind up under - not the
 * orphan dir!
 * @dir_bh: buffer_head the @dir inode block
 * @orphan_name: string of length (CFS2_ORPHAN_NAMELEN + 1). Will be filled
 * with the string to be used for orphan dirent. Pass back to the orphan dir
 * code.
 * @ret_orphan_dir: orphan dir inode returned to be passed back into orphan
 * dir code.
 * @ret_di_blkno: block number where the new inode will be allocated.
 * @orphan_insert: Dir insert context to be passed back into orphan dir code.
 * @ret_inode_ac: Inode alloc context to be passed back to the allocator.
 *
 * Returns zero on success and the ret_orphan_dir, name and lookup
 * fields will be populated.
 *
 * Returns non-zero on failure. 
 */
static int ocfs2_prep_new_orphaned_file(struct inode *dir,
					struct buffer_head *dir_bh,
					char *orphan_name,
					struct inode **ret_orphan_dir,
					u64 *ret_di_blkno,
					struct ocfs2_dir_lookup_result *orphan_insert,
					struct ocfs2_alloc_context **ret_inode_ac)
{}

int ocfs2_create_inode_in_orphan(struct inode *dir,
				 int mode,
				 struct inode **new_inode)
{}

int ocfs2_add_inode_to_orphan(struct ocfs2_super *osb,
	struct inode *inode)
{}

int ocfs2_del_inode_from_orphan(struct ocfs2_super *osb,
		struct inode *inode, struct buffer_head *di_bh,
		int update_isize, loff_t end)
{}

int ocfs2_mv_orphaned_inode_to_new(struct inode *dir,
				   struct inode *inode,
				   struct dentry *dentry)
{}

const struct inode_operations ocfs2_dir_iops =;