fs/nfsd/blocklayout.c

Source file repositories/reference/linux-study-clean/fs/nfsd/blocklayout.c

File Facts

System
Linux kernel
Corpus path
fs/nfsd/blocklayout.c
Extension
.c
Size
14365 bytes
Lines
527
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

if (iomode & IOMODE_RW) {
			/*
			 * Crack monkey special case from section 2.3.1.
			 */
			if (minlength == 0) {
				dprintk("pnfsd: no soup for you!\n");
				return nfserr_layoutunavailable;
			}

			bex->es = PNFS_BLOCK_INVALID_DATA;
			bex->soff = iomap.addr;
			break;
		}
		fallthrough;
	case IOMAP_HOLE:
		if (iomode == IOMODE_READ) {
			bex->es = PNFS_BLOCK_NONE_DATA;
			break;
		}
		fallthrough;
	case IOMAP_DELALLOC:
	default:
		WARN(1, "pnfsd: filesystem returned %d extent\n", iomap.type);
		return nfserr_layoutunavailable;
	}

	error = nfsd4_set_deviceid(&bex->vol_id, fhp, device_generation);
	if (error)
		return nfserrno(error);

	bex->foff = iomap.offset;
	bex->len = iomap.length;
	return nfs_ok;
}

static __be32
nfsd4_block_proc_layoutget(struct svc_rqst *rqstp, struct inode *inode,
		const struct svc_fh *fhp, struct nfsd4_layoutget *args)
{
	struct nfsd4_layout_seg *seg = &args->lg_seg;
	struct pnfs_block_layout *bl;
	struct pnfs_block_extent *first_bex, *last_bex;
	u64 offset = seg->offset, length = seg->length;
	u32 i, nr_extents_max, block_size = i_blocksize(inode);
	__be32 nfserr;

	if (locks_in_grace(SVC_NET(rqstp)))
		return nfserr_grace;

	nfserr = nfserr_layoutunavailable;
	if (seg->offset & (block_size - 1)) {
		dprintk("pnfsd: I/O misaligned\n");
		goto out_error;
	}

	/*
	 * RFC 8881, section 3.3.17:
	 *   The layout4 data type defines a layout for a file.
	 *
	 * RFC 8881, section 18.43.3:
	 *   The loga_maxcount field specifies the maximum layout size
	 *   (in bytes) that the client can handle. If the size of the
	 *   layout structure exceeds the size specified by maxcount,
	 *   the metadata server will return the NFS4ERR_TOOSMALL error.
	 */
	nfserr = nfserr_toosmall;
	if (args->lg_maxcount < PNFS_BLOCK_LAYOUT4_SIZE +
				PNFS_BLOCK_EXTENT_SIZE)
		goto out_error;

	/*
	 * Limit the maximum layout size to avoid allocating
	 * a large buffer on the server for each layout request.
	 */
	nr_extents_max = (min(args->lg_maxcount, PAGE_SIZE) -
			  PNFS_BLOCK_LAYOUT4_SIZE) / PNFS_BLOCK_EXTENT_SIZE;

	/*
	 * Some clients barf on non-zero block numbers for NONE or INVALID
	 * layouts, so make sure to zero the whole structure.
	 */
	nfserr = nfserrno(-ENOMEM);
	bl = kzalloc_flex(*bl, extents, nr_extents_max);
	if (!bl)
		goto out_error;
	bl->nr_extents = nr_extents_max;
	args->lg_content = bl;

	for (i = 0; i < bl->nr_extents; i++) {
		struct pnfs_block_extent *bex = bl->extents + i;

Annotation

Implementation Notes