Changeset View
Changeset View
Standalone View
Standalone View
sys/fs/tmpfs/tmpfs_subr.c
Show First 20 Lines • Show All 69 Lines • ▼ Show 20 Lines | |||||
SYSCTL_NODE(_vfs, OID_AUTO, tmpfs, CTLFLAG_RW | CTLFLAG_MPSAFE, 0, | SYSCTL_NODE(_vfs, OID_AUTO, tmpfs, CTLFLAG_RW | CTLFLAG_MPSAFE, 0, | ||||
"tmpfs file system"); | "tmpfs file system"); | ||||
static long tmpfs_pages_reserved = TMPFS_PAGES_MINRESERVED; | static long tmpfs_pages_reserved = TMPFS_PAGES_MINRESERVED; | ||||
static uma_zone_t tmpfs_dirent_pool; | static uma_zone_t tmpfs_dirent_pool; | ||||
static uma_zone_t tmpfs_node_pool; | static uma_zone_t tmpfs_node_pool; | ||||
VFS_SMR_DECLARE; | |||||
static int | static int | ||||
tmpfs_node_ctor(void *mem, int size, void *arg, int flags) | tmpfs_node_ctor(void *mem, int size, void *arg, int flags) | ||||
{ | { | ||||
struct tmpfs_node *node; | struct tmpfs_node *node; | ||||
node = mem; | node = mem; | ||||
node->tn_gen++; | node->tn_gen++; | ||||
Show All 40 Lines | |||||
tmpfs_subr_init(void) | tmpfs_subr_init(void) | ||||
{ | { | ||||
tmpfs_dirent_pool = uma_zcreate("TMPFS dirent", | tmpfs_dirent_pool = uma_zcreate("TMPFS dirent", | ||||
sizeof(struct tmpfs_dirent), NULL, NULL, NULL, NULL, | sizeof(struct tmpfs_dirent), NULL, NULL, NULL, NULL, | ||||
UMA_ALIGN_PTR, 0); | UMA_ALIGN_PTR, 0); | ||||
tmpfs_node_pool = uma_zcreate("TMPFS node", | tmpfs_node_pool = uma_zcreate("TMPFS node", | ||||
sizeof(struct tmpfs_node), tmpfs_node_ctor, tmpfs_node_dtor, | sizeof(struct tmpfs_node), tmpfs_node_ctor, tmpfs_node_dtor, | ||||
tmpfs_node_init, tmpfs_node_fini, UMA_ALIGN_PTR, 0); | tmpfs_node_init, tmpfs_node_fini, UMA_ALIGN_PTR, 0); | ||||
VFS_SMR_ZONE_SET(tmpfs_node_pool); | |||||
} | } | ||||
void | void | ||||
tmpfs_subr_uninit(void) | tmpfs_subr_uninit(void) | ||||
{ | { | ||||
uma_zdestroy(tmpfs_node_pool); | uma_zdestroy(tmpfs_node_pool); | ||||
uma_zdestroy(tmpfs_dirent_pool); | uma_zdestroy(tmpfs_dirent_pool); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 141 Lines • ▼ Show 20 Lines | if ((mp->mnt_kern_flag & MNTK_UNMOUNT) != 0) { | ||||
* Tmpfs does not need to instantiate new nodes during | * Tmpfs does not need to instantiate new nodes during | ||||
* unmount. | * unmount. | ||||
*/ | */ | ||||
return (EBUSY); | return (EBUSY); | ||||
} | } | ||||
if ((mp->mnt_kern_flag & MNT_RDONLY) != 0) | if ((mp->mnt_kern_flag & MNT_RDONLY) != 0) | ||||
return (EROFS); | return (EROFS); | ||||
nnode = uma_zalloc_arg(tmpfs_node_pool, tmp, M_WAITOK); | nnode = uma_zalloc_smr(tmpfs_node_pool, M_WAITOK); | ||||
/* Generic initialization. */ | /* Generic initialization. */ | ||||
nnode->tn_type = type; | nnode->tn_type = type; | ||||
vfs_timestamp(&nnode->tn_atime); | vfs_timestamp(&nnode->tn_atime); | ||||
nnode->tn_birthtime = nnode->tn_ctime = nnode->tn_mtime = | nnode->tn_birthtime = nnode->tn_ctime = nnode->tn_mtime = | ||||
nnode->tn_atime; | nnode->tn_atime; | ||||
nnode->tn_uid = uid; | nnode->tn_uid = uid; | ||||
nnode->tn_gid = gid; | nnode->tn_gid = gid; | ||||
▲ Show 20 Lines • Show All 130 Lines • ▼ Show 20 Lines | if (uobj != NULL) { | ||||
vm_object_deallocate(uobj); | vm_object_deallocate(uobj); | ||||
} | } | ||||
break; | break; | ||||
default: | default: | ||||
panic("tmpfs_free_node: type %p %d", node, (int)node->tn_type); | panic("tmpfs_free_node: type %p %d", node, (int)node->tn_type); | ||||
} | } | ||||
uma_zfree(tmpfs_node_pool, node); | uma_zfree_smr(tmpfs_node_pool, node); | ||||
TMPFS_LOCK(tmp); | TMPFS_LOCK(tmp); | ||||
tmpfs_free_tmp(tmp); | tmpfs_free_tmp(tmp); | ||||
return (true); | return (true); | ||||
} | } | ||||
static __inline uint32_t | static __inline uint32_t | ||||
tmpfs_dirent_hash(const char *name, u_int len) | tmpfs_dirent_hash(const char *name, u_int len) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 1,170 Lines • ▼ Show 20 Lines | |||||
/* | /* | ||||
* Change access mode on the given vnode. | * Change access mode on the given vnode. | ||||
* Caller should execute tmpfs_update on vp after a successful execution. | * Caller should execute tmpfs_update on vp after a successful execution. | ||||
* The vnode must be locked on entry and remain locked on exit. | * The vnode must be locked on entry and remain locked on exit. | ||||
*/ | */ | ||||
int | int | ||||
tmpfs_chmod(struct vnode *vp, mode_t mode, struct ucred *cred, struct thread *p) | tmpfs_chmod(struct vnode *vp, mode_t mode, struct ucred *cred, struct thread *p) | ||||
{ | { | ||||
int error; | int error, newmode; | ||||
struct tmpfs_node *node; | struct tmpfs_node *node; | ||||
ASSERT_VOP_ELOCKED(vp, "chmod"); | ASSERT_VOP_ELOCKED(vp, "chmod"); | ||||
ASSERT_VOP_IN_SEQC(vp); | |||||
node = VP_TO_TMPFS_NODE(vp); | node = VP_TO_TMPFS_NODE(vp); | ||||
/* Disallow this operation if the file system is mounted read-only. */ | /* Disallow this operation if the file system is mounted read-only. */ | ||||
if (vp->v_mount->mnt_flag & MNT_RDONLY) | if (vp->v_mount->mnt_flag & MNT_RDONLY) | ||||
return EROFS; | return EROFS; | ||||
/* Immutable or append-only files cannot be modified, either. */ | /* Immutable or append-only files cannot be modified, either. */ | ||||
Show All 17 Lines | if (priv_check_cred(cred, PRIV_VFS_STICKYFILE)) | ||||
return (EFTYPE); | return (EFTYPE); | ||||
} | } | ||||
if (!groupmember(node->tn_gid, cred) && (mode & S_ISGID)) { | if (!groupmember(node->tn_gid, cred) && (mode & S_ISGID)) { | ||||
error = priv_check_cred(cred, PRIV_VFS_SETGID); | error = priv_check_cred(cred, PRIV_VFS_SETGID); | ||||
if (error) | if (error) | ||||
return (error); | return (error); | ||||
} | } | ||||
newmode = node->tn_mode & ~ALLPERMS; | |||||
newmode |= mode & ALLPERMS; | |||||
atomic_store_int(&node->tn_mode, newmode); | |||||
node->tn_mode &= ~ALLPERMS; | |||||
node->tn_mode |= mode & ALLPERMS; | |||||
node->tn_status |= TMPFS_NODE_CHANGED; | node->tn_status |= TMPFS_NODE_CHANGED; | ||||
ASSERT_VOP_ELOCKED(vp, "chmod2"); | ASSERT_VOP_ELOCKED(vp, "chmod2"); | ||||
return (0); | return (0); | ||||
} | } | ||||
/* | /* | ||||
* Change ownership of the given vnode. At least one of uid or gid must | * Change ownership of the given vnode. At least one of uid or gid must | ||||
* be different than VNOVAL. If one is set to that value, the attribute | * be different than VNOVAL. If one is set to that value, the attribute | ||||
* is unchanged. | * is unchanged. | ||||
* Caller should execute tmpfs_update on vp after a successful execution. | * Caller should execute tmpfs_update on vp after a successful execution. | ||||
* The vnode must be locked on entry and remain locked on exit. | * The vnode must be locked on entry and remain locked on exit. | ||||
*/ | */ | ||||
int | int | ||||
tmpfs_chown(struct vnode *vp, uid_t uid, gid_t gid, struct ucred *cred, | tmpfs_chown(struct vnode *vp, uid_t uid, gid_t gid, struct ucred *cred, | ||||
struct thread *p) | struct thread *p) | ||||
{ | { | ||||
int error; | int error; | ||||
struct tmpfs_node *node; | struct tmpfs_node *node; | ||||
uid_t ouid; | uid_t ouid; | ||||
gid_t ogid; | gid_t ogid; | ||||
ASSERT_VOP_ELOCKED(vp, "chown"); | ASSERT_VOP_ELOCKED(vp, "chown"); | ||||
ASSERT_VOP_IN_SEQC(vp); | |||||
node = VP_TO_TMPFS_NODE(vp); | node = VP_TO_TMPFS_NODE(vp); | ||||
/* Assign default values if they are unknown. */ | /* Assign default values if they are unknown. */ | ||||
MPASS(uid != VNOVAL || gid != VNOVAL); | MPASS(uid != VNOVAL || gid != VNOVAL); | ||||
if (uid == VNOVAL) | if (uid == VNOVAL) | ||||
uid = node->tn_uid; | uid = node->tn_uid; | ||||
if (gid == VNOVAL) | if (gid == VNOVAL) | ||||
Show All 30 Lines | tmpfs_chown(struct vnode *vp, uid_t uid, gid_t gid, struct ucred *cred, | ||||
node->tn_uid = uid; | node->tn_uid = uid; | ||||
node->tn_gid = gid; | node->tn_gid = gid; | ||||
node->tn_status |= TMPFS_NODE_CHANGED; | node->tn_status |= TMPFS_NODE_CHANGED; | ||||
if ((node->tn_mode & (S_ISUID | S_ISGID)) && (ouid != uid || ogid != gid)) { | if ((node->tn_mode & (S_ISUID | S_ISGID)) && (ouid != uid || ogid != gid)) { | ||||
if (priv_check_cred(cred, PRIV_VFS_RETAINSUGID)) | if (priv_check_cred(cred, PRIV_VFS_RETAINSUGID)) | ||||
node->tn_mode &= ~(S_ISUID | S_ISGID); | atomic_store_int(&node->tn_mode, node->tn_mode & ~(S_ISUID | S_ISGID)); | ||||
} | } | ||||
ASSERT_VOP_ELOCKED(vp, "chown2"); | ASSERT_VOP_ELOCKED(vp, "chown2"); | ||||
return (0); | return (0); | ||||
} | } | ||||
/* | /* | ||||
▲ Show 20 Lines • Show All 190 Lines • Show Last 20 Lines |