fs/smb/client/reparse.c

Source file repositories/reference/linux-study-clean/fs/smb/client/reparse.c

File Facts

System
Linux kernel
Corpus path
fs/smb/client/reparse.c
Extension
.c
Size
38326 bytes
Lines
1275
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

struct wsl_xattr {
	const char	*name;
	__le64		value;
	u16		size;
	u32		next;
};

static int wsl_set_xattrs(struct inode *inode, umode_t _mode,
			  dev_t _dev, struct kvec *iov)
{
	struct smb2_file_full_ea_info *ea;
	struct smb2_create_ea_ctx *cc;
	struct smb3_fs_context *ctx = CIFS_SB(inode->i_sb)->ctx;
	__le64 uid = cpu_to_le64(from_kuid(current_user_ns(), ctx->linux_uid));
	__le64 gid = cpu_to_le64(from_kgid(current_user_ns(), ctx->linux_gid));
	__le64 dev = cpu_to_le64(((u64)MINOR(_dev) << 32) | MAJOR(_dev));
	__le64 mode = cpu_to_le64(_mode);
	struct wsl_xattr xattrs[] = {
		{ .name = SMB2_WSL_XATTR_UID,  .value = uid,  .size = SMB2_WSL_XATTR_UID_SIZE, },
		{ .name = SMB2_WSL_XATTR_GID,  .value = gid,  .size = SMB2_WSL_XATTR_GID_SIZE, },
		{ .name = SMB2_WSL_XATTR_MODE, .value = mode, .size = SMB2_WSL_XATTR_MODE_SIZE, },
		{ .name = SMB2_WSL_XATTR_DEV,  .value = dev, .size = SMB2_WSL_XATTR_DEV_SIZE, },
	};
	size_t cc_len;
	u32 dlen = 0, next = 0;
	int i, num_xattrs;
	u8 name_size = SMB2_WSL_XATTR_NAME_LEN + 1;

	memset(iov, 0, sizeof(*iov));

	/* Exclude $LXDEV xattr for non-device files */
	if (!S_ISBLK(_mode) && !S_ISCHR(_mode))
		num_xattrs = ARRAY_SIZE(xattrs) - 1;
	else
		num_xattrs = ARRAY_SIZE(xattrs);

	for (i = 0; i < num_xattrs; i++) {
		xattrs[i].next = ALIGN(sizeof(*ea) + name_size +
				       xattrs[i].size, 4);
		dlen += xattrs[i].next;
	}

	cc = ea_create_context(dlen, &cc_len);
	if (IS_ERR(cc))
		return PTR_ERR(cc);

	ea = &cc->ea;
	for (i = 0; i < num_xattrs; i++) {
		ea = (void *)((u8 *)ea + next);
		next = xattrs[i].next;
		ea->next_entry_offset = cpu_to_le32(next);

		ea->ea_name_length = name_size - 1;
		ea->ea_value_length = cpu_to_le16(xattrs[i].size);
		memcpy(ea->ea_data, xattrs[i].name, name_size);
		memcpy(&ea->ea_data[name_size],
		       &xattrs[i].value, xattrs[i].size);
	}
	ea->next_entry_offset = 0;

	iov->iov_base = cc;
	iov->iov_len = cc_len;
	return 0;
}

static int mknod_wsl(unsigned int xid, struct inode *inode,
		     struct dentry *dentry, struct cifs_tcon *tcon,
		     const char *full_path, umode_t mode, dev_t dev,
		     const char *symname)
{
	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
	struct cifs_open_info_data data;
	struct reparse_data_buffer *buf;
	struct smb2_create_ea_ctx *cc;
	struct inode *new;
	unsigned int len;
	struct kvec reparse_iov, xattr_iov;
	int rc;

	rc = wsl_set_reparse_buf(&buf, mode, symname, cifs_sb, &reparse_iov);
	if (rc)
		return rc;

	rc = wsl_set_xattrs(inode, mode, dev, &xattr_iov);
	if (rc) {
		kfree(buf);
		return rc;
	}

	data = (struct cifs_open_info_data) {

Annotation

Implementation Notes