fs/afs/dir_silly.c

Source file repositories/reference/linux-study-clean/fs/afs/dir_silly.c

File Facts

System
Linux kernel
Corpus path
fs/afs/dir_silly.c
Extension
.c
Size
7891 bytes
Lines
290
Domain
Core OS
Bucket
VFS And Filesystem Core
Inferred role
Core OS: implementation source
Status
source implementation candidate

Why This File Exists

Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.

Dependency Surface

Detected Declarations

Annotated Snippet

// SPDX-License-Identifier: GPL-2.0-or-later
/* AFS silly rename handling
 *
 * Copyright (C) 2019 Red Hat, Inc. All Rights Reserved.
 * Written by David Howells (dhowells@redhat.com)
 * - Derived from NFS's sillyrename.
 */

#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/namei.h>
#include <linux/fsnotify.h>
#include "internal.h"

static void afs_silly_rename_success(struct afs_operation *op)
{
	_enter("op=%08x", op->debug_id);

	afs_check_dir_conflict(op, &op->file[0]);
	afs_vnode_commit_status(op, &op->file[0]);
}

static void afs_silly_rename_edit_dir(struct afs_operation *op)
{
	struct afs_vnode_param *dvp = &op->file[0];
	struct afs_vnode *dvnode = dvp->vnode;
	struct afs_vnode *vnode = AFS_FS_I(d_inode(op->dentry));
	struct dentry *old = op->dentry;
	struct dentry *new = op->dentry_2;

	spin_lock(&old->d_lock);
	old->d_flags |= DCACHE_NFSFS_RENAMED;
	spin_unlock(&old->d_lock);
	if (dvnode->silly_key != op->key) {
		key_put(dvnode->silly_key);
		dvnode->silly_key = key_get(op->key);
	}

	down_write(&dvnode->validate_lock);
	if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags) &&
	    dvnode->status.data_version == dvp->dv_before + dvp->dv_delta) {
		afs_edit_dir_remove(dvnode, &old->d_name,
				    afs_edit_dir_for_silly_0);
		afs_edit_dir_add(dvnode, &new->d_name,
				 &vnode->fid, afs_edit_dir_for_silly_1);
	}
	up_write(&dvnode->validate_lock);
}

static const struct afs_operation_ops afs_silly_rename_operation = {
	.issue_afs_rpc	= afs_fs_rename,
	.issue_yfs_rpc	= yfs_fs_rename,
	.success	= afs_silly_rename_success,
	.edit_dir	= afs_silly_rename_edit_dir,
};

/*
 * Actually perform the silly rename step.
 */
static int afs_do_silly_rename(struct afs_vnode *dvnode, struct afs_vnode *vnode,
			       struct dentry *old, struct dentry *new,
			       struct key *key)
{
	struct afs_operation *op;

	_enter("%pd,%pd", old, new);

	op = afs_alloc_operation(key, dvnode->volume);
	if (IS_ERR(op))
		return PTR_ERR(op);

	op->more_files = kvzalloc_objs(struct afs_vnode_param, 2);
	if (!op->more_files) {
		afs_put_operation(op);
		return -ENOMEM;
	}

	afs_op_set_vnode(op, 0, dvnode);
	afs_op_set_vnode(op, 1, dvnode);
	op->file[0].dv_delta = 1;
	op->file[1].dv_delta = 1;
	op->file[0].modification = true;
	op->file[1].modification = true;
	op->file[0].update_ctime = true;
	op->file[1].update_ctime = true;
	op->more_files[0].vnode		= AFS_FS_I(d_inode(old));
	op->more_files[0].speculative	= true;
	op->more_files[1].vnode		= AFS_FS_I(d_inode(new));
	op->more_files[1].speculative	= true;
	op->nr_files = 4;

Annotation

Implementation Notes