fs/xfs/xfs_pnfs.c

Source file repositories/reference/linux-study-clean/fs/xfs/xfs_pnfs.c

File Facts

System
Linux kernel
Corpus path
fs/xfs/xfs_pnfs.c
Extension
.c
Size
9181 bytes
Lines
358
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
/*
 * Copyright (c) 2014 Christoph Hellwig.
 */
#include "xfs_platform.h"
#include "xfs_shared.h"
#include "xfs_format.h"
#include "xfs_log_format.h"
#include "xfs_trans_resv.h"
#include "xfs_mount.h"
#include "xfs_inode.h"
#include "xfs_trans.h"
#include "xfs_bmap.h"
#include "xfs_iomap.h"
#include "xfs_pnfs.h"
#include <linux/exportfs_block.h>

/*
 * Ensure that we do not have any outstanding pNFS layouts that can be used by
 * clients to directly read from or write to this inode.  This must be called
 * before every operation that can remove blocks from the extent map.
 * Additionally we call it during the write operation, where aren't concerned
 * about exposing unallocated blocks but just want to provide basic
 * synchronization between a local writer and pNFS clients.  mmap writes would
 * also benefit from this sort of synchronization, but due to the tricky locking
 * rules in the page fault path we don't bother.
 */
int
xfs_break_leased_layouts(
	struct inode		*inode,
	uint			*iolock,
	bool			*did_unlock)
{
	struct xfs_inode	*ip = XFS_I(inode);
	int			error;

	while ((error = break_layout(inode, false)) == -EWOULDBLOCK) {
		xfs_iunlock(ip, *iolock);
		*did_unlock = true;
		error = break_layout(inode, true);
		*iolock &= ~XFS_IOLOCK_SHARED;
		*iolock |= XFS_IOLOCK_EXCL;
		xfs_ilock(ip, *iolock);
	}

	return error;
}

static expfs_block_layouts_t
xfs_fs_layouts_supported(
	struct super_block	*sb)
{
	expfs_block_layouts_t	supported = EXPFS_BLOCK_IN_BAND_ID;

	if (exportfs_bdev_supports_out_of_band_id(sb->s_bdev))
		supported |= EXPFS_BLOCK_OUT_OF_BAND_ID;
	return supported;
}

/*
 * Get a unique ID including its location so that the client can identify
 * the exported device.
 */
static int
xfs_fs_get_uuid(
	struct super_block	*sb,
	u8			*buf,
	u32			*len,
	u64			*offset)
{
	struct xfs_mount	*mp = XFS_M(sb);

	if (*len < sizeof(uuid_t))
		return -EINVAL;

	memcpy(buf, &mp->m_sb.sb_uuid, sizeof(uuid_t));
	*len = sizeof(uuid_t);
	*offset = offsetof(struct xfs_dsb, sb_uuid);
	return 0;
}

/*
 * We cannot use file based VFS helpers such as file_modified() to update
 * inode state as we modify the data/metadata in the inode here. Hence we have
 * to open code the timestamp updates and SUID/SGID stripping. We also need
 * to set the inode prealloc flag to ensure that the extents we allocate are not
 * removed if the inode is reclaimed from memory before xfs_fs_block_commit()
 * is from the client to indicate that data has been written and the file size
 * can be extended.
 */

Annotation

Implementation Notes