⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vfs_inode.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
		inode = NULL;		goto error;	}	result = v9fs_fid_add(dentry, fid);	if (result < 0)		goto error;	if ((fid->qid.version) && (v9ses->cache))		dentry->d_op = &v9fs_cached_dentry_operations;	else		dentry->d_op = &v9fs_dentry_operations;	d_add(dentry, inode);	return NULL;error:	if (fid)		p9_client_clunk(fid);	return ERR_PTR(result);}/** * v9fs_vfs_unlink - VFS unlink hook to delete an inode * @i:  inode that is being unlinked * @d: dentry that is being unlinked * */static int v9fs_vfs_unlink(struct inode *i, struct dentry *d){	return v9fs_remove(i, d, 0);}/** * v9fs_vfs_rmdir - VFS unlink hook to delete a directory * @i:  inode that is being unlinked * @d: dentry that is being unlinked * */static int v9fs_vfs_rmdir(struct inode *i, struct dentry *d){	return v9fs_remove(i, d, 1);}/** * v9fs_vfs_rename - VFS hook to rename an inode * @old_dir:  old dir inode * @old_dentry: old dentry * @new_dir: new dir inode * @new_dentry: new dentry * */static intv9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry,		struct inode *new_dir, struct dentry *new_dentry){	struct inode *old_inode;	struct v9fs_session_info *v9ses;	struct p9_fid *oldfid;	struct p9_fid *olddirfid;	struct p9_fid *newdirfid;	struct p9_wstat wstat;	int retval;	P9_DPRINTK(P9_DEBUG_VFS, "\n");	retval = 0;	old_inode = old_dentry->d_inode;	v9ses = v9fs_inode2v9ses(old_inode);	oldfid = v9fs_fid_lookup(old_dentry);	if (IS_ERR(oldfid))		return PTR_ERR(oldfid);	olddirfid = v9fs_fid_clone(old_dentry->d_parent);	if (IS_ERR(olddirfid)) {		retval = PTR_ERR(olddirfid);		goto done;	}	newdirfid = v9fs_fid_clone(new_dentry->d_parent);	if (IS_ERR(newdirfid)) {		retval = PTR_ERR(newdirfid);		goto clunk_olddir;	}	/* 9P can only handle file rename in the same directory */	if (memcmp(&olddirfid->qid, &newdirfid->qid, sizeof(newdirfid->qid))) {		P9_DPRINTK(P9_DEBUG_ERROR,				"old dir and new dir are different\n");		retval = -EXDEV;		goto clunk_newdir;	}	v9fs_blank_wstat(&wstat);	wstat.muid = v9ses->uname;	wstat.name = (char *) new_dentry->d_name.name;	retval = p9_client_wstat(oldfid, &wstat);clunk_newdir:	p9_client_clunk(newdirfid);clunk_olddir:	p9_client_clunk(olddirfid);done:	return retval;}/** * v9fs_vfs_getattr - retrieve file metadata * @mnt - mount information * @dentry - file to get attributes on * @stat - metadata structure to populate * */static intv9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry,		 struct kstat *stat){	int err;	struct v9fs_session_info *v9ses;	struct p9_fid *fid;	struct p9_stat *st;	P9_DPRINTK(P9_DEBUG_VFS, "dentry: %p\n", dentry);	err = -EPERM;	v9ses = v9fs_inode2v9ses(dentry->d_inode);	if (v9ses->cache == CACHE_LOOSE)		return simple_getattr(mnt, dentry, stat);	fid = v9fs_fid_lookup(dentry);	if (IS_ERR(fid))		return PTR_ERR(fid);	st = p9_client_stat(fid);	if (IS_ERR(st))		return PTR_ERR(st);	v9fs_stat2inode(st, dentry->d_inode, dentry->d_inode->i_sb);		generic_fillattr(dentry->d_inode, stat);	kfree(st);	return 0;}/** * v9fs_vfs_setattr - set file metadata * @dentry: file whose metadata to set * @iattr: metadata assignment structure * */static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr){	int retval;	struct v9fs_session_info *v9ses;	struct p9_fid *fid;	struct p9_wstat wstat;	P9_DPRINTK(P9_DEBUG_VFS, "\n");	retval = -EPERM;	v9ses = v9fs_inode2v9ses(dentry->d_inode);	fid = v9fs_fid_lookup(dentry);	if(IS_ERR(fid))		return PTR_ERR(fid);	v9fs_blank_wstat(&wstat);	if (iattr->ia_valid & ATTR_MODE)		wstat.mode = unixmode2p9mode(v9ses, iattr->ia_mode);	if (iattr->ia_valid & ATTR_MTIME)		wstat.mtime = iattr->ia_mtime.tv_sec;	if (iattr->ia_valid & ATTR_ATIME)		wstat.atime = iattr->ia_atime.tv_sec;	if (iattr->ia_valid & ATTR_SIZE)		wstat.length = iattr->ia_size;	if (v9fs_extended(v9ses)) {		if (iattr->ia_valid & ATTR_UID)			wstat.n_uid = iattr->ia_uid;		if (iattr->ia_valid & ATTR_GID)			wstat.n_gid = iattr->ia_gid;	}	retval = p9_client_wstat(fid, &wstat);	if (retval >= 0)		retval = inode_setattr(dentry->d_inode, iattr);	return retval;}/** * v9fs_stat2inode - populate an inode structure with mistat info * @stat: Plan 9 metadata (mistat) structure * @inode: inode to populate * @sb: superblock of filesystem * */voidv9fs_stat2inode(struct p9_stat *stat, struct inode *inode,	struct super_block *sb){	int n;	char ext[32];	struct v9fs_session_info *v9ses = sb->s_fs_info;	inode->i_nlink = 1;	inode->i_atime.tv_sec = stat->atime;	inode->i_mtime.tv_sec = stat->mtime;	inode->i_ctime.tv_sec = stat->mtime;	inode->i_uid = v9ses->dfltuid;	inode->i_gid = v9ses->dfltgid;	if (v9fs_extended(v9ses)) {		inode->i_uid = stat->n_uid;		inode->i_gid = stat->n_gid;	}	inode->i_mode = p9mode2unixmode(v9ses, stat->mode);	if ((S_ISBLK(inode->i_mode)) || (S_ISCHR(inode->i_mode))) {		char type = 0;		int major = -1;		int minor = -1;		n = stat->extension.len;		if (n > sizeof(ext)-1)			n = sizeof(ext)-1;		memmove(ext, stat->extension.str, n);		ext[n] = 0;		sscanf(ext, "%c %u %u", &type, &major, &minor);		switch (type) {		case 'c':			inode->i_mode &= ~S_IFBLK;			inode->i_mode |= S_IFCHR;			break;		case 'b':			break;		default:			P9_DPRINTK(P9_DEBUG_ERROR,				"Unknown special type %c (%.*s)\n", type,				stat->extension.len, stat->extension.str);		};		inode->i_rdev = MKDEV(major, minor);	} else		inode->i_rdev = 0;	inode->i_size = stat->length;	/* not real number of blocks, but 512 byte ones ... */	inode->i_blocks = (inode->i_size + 512 - 1) >> 9;}/** * v9fs_qid2ino - convert qid into inode number * @qid: qid to hash * * BUG: potential for inode number collisions? */ino_t v9fs_qid2ino(struct p9_qid *qid){	u64 path = qid->path + 2;	ino_t i = 0;	if (sizeof(ino_t) == sizeof(path))		memcpy(&i, &path, sizeof(ino_t));	else		i = (ino_t) (path ^ (path >> 32));	return i;}/** * v9fs_readlink - read a symlink's location (internal version) * @dentry: dentry for symlink * @buffer: buffer to load symlink location into * @buflen: length of buffer * */static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen){	int retval;	struct v9fs_session_info *v9ses;	struct p9_fid *fid;	struct p9_stat *st;	P9_DPRINTK(P9_DEBUG_VFS, " %s\n", dentry->d_name.name);	retval = -EPERM;	v9ses = v9fs_inode2v9ses(dentry->d_inode);	fid = v9fs_fid_lookup(dentry);	if (IS_ERR(fid))		return PTR_ERR(fid);	if (!v9fs_extended(v9ses))		return -EBADF;	st = p9_client_stat(fid);	if (IS_ERR(st))		return PTR_ERR(st);	if (!(st->mode & P9_DMSYMLINK)) {		retval = -EINVAL;		goto done;	}	/* copy extension buffer into buffer */	if (st->extension.len < buflen)		buflen = st->extension.len + 1;	memmove(buffer, st->extension.str, buflen - 1);	buffer[buflen-1] = 0;	P9_DPRINTK(P9_DEBUG_VFS,		"%s -> %.*s (%s)\n", dentry->d_name.name, st->extension.len,		st->extension.str, buffer);	retval = buflen;done:	kfree(st);	return retval;}/** * v9fs_vfs_readlink - read a symlink's location * @dentry: dentry for symlink * @buf: buffer to load symlink location into * @buflen: length of buffer * */static int v9fs_vfs_readlink(struct dentry *dentry, char __user * buffer,			     int buflen){	int retval;	int ret;	char *link = __getname();	if (unlikely(!link))		return -ENOMEM;	if (buflen > PATH_MAX)		buflen = PATH_MAX;	P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry);	retval = v9fs_readlink(dentry, link, buflen);	if (retval > 0) {		if ((ret = copy_to_user(buffer, link, retval)) != 0) {			P9_DPRINTK(P9_DEBUG_ERROR,					"problem copying to user: %d\n", ret);			retval = ret;		}	}	__putname(link);	return retval;}/** * v9fs_vfs_follow_link - follow a symlink path * @dentry: dentry for symlink * @nd: nameidata * */static void *v9fs_vfs_follow_link(struct dentry *dentry, struct nameidata *nd){	int len = 0;	char *link = __getname();	P9_DPRINTK(P9_DEBUG_VFS, "%s n", dentry->d_name.name);	if (!link)		link = ERR_PTR(-ENOMEM);	else {		len = v9fs_readlink(dentry, link, PATH_MAX);		if (len < 0) {			__putname(link);			link = ERR_PTR(len);		} else			link[len] = 0;	}	nd_set_link(nd, link);	return NULL;}/** * v9fs_vfs_put_link - release a symlink path * @dentry: dentry for symlink * @nd: nameidata * */static void v9fs_vfs_put_link(struct dentry *dentry, struct nameidata *nd, void *p){	char *s = nd_get_link(nd);	P9_DPRINTK(P9_DEBUG_VFS, " %s %s\n", dentry->d_name.name, s);	if (!IS_ERR(s))		__putname(s);}static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry,	int mode, const char *extension){	u32 perm;	struct v9fs_session_info *v9ses;	struct p9_fid *fid;	v9ses = v9fs_inode2v9ses(dir);	if (!v9fs_extended(v9ses)) {		P9_DPRINTK(P9_DEBUG_ERROR, "not extended\n");		return -EPERM;	}	perm = unixmode2p9mode(v9ses, mode);	fid = v9fs_create(v9ses, dir, dentry, (char *) extension, perm,								P9_OREAD);	if (IS_ERR(fid))		return PTR_ERR(fid);	p9_client_clunk(fid);	return 0;}/** * v9fs_vfs_symlink - helper function to create symlinks * @dir: directory inode containing symlink * @dentry: dentry for symlink * @symname: symlink data * * See 9P2000.u RFC for more information * */static intv9fs_vfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname){	P9_DPRINTK(P9_DEBUG_VFS, " %lu,%s,%s\n", dir->i_ino,					dentry->d_name.name, symname);	return v9fs_vfs_mkspecial(dir, dentry, S_IFLNK, symname);}/** * v9fs_vfs_link - create a hardlink * @old_dentry: dentry for file to link to * @dir: inode destination for new link * @dentry: dentry for link * *//* XXX - lots of code dup'd from symlink and creates, * figure out a better reuse strategy */static intv9fs_vfs_link(struct dentry *old_dentry, struct inode *dir,	      struct dentry *dentry){	int retval;	struct p9_fid *oldfid;	char *name;	P9_DPRINTK(P9_DEBUG_VFS,		" %lu,%s,%s\n", dir->i_ino, dentry->d_name.name,		old_dentry->d_name.name);	oldfid = v9fs_fid_clone(old_dentry);	if (IS_ERR(oldfid))		return PTR_ERR(oldfid);	name = __getname();	if (unlikely(!name)) {		retval = -ENOMEM;		goto clunk_fid;	}	sprintf(name, "%d\n", oldfid->fid);	retval = v9fs_vfs_mkspecial(dir, dentry, P9_DMLINK, name);	__putname(name);clunk_fid:	p9_client_clunk(oldfid);	return retval;}/** * v9fs_vfs_mknod - create a special file * @dir: inode destination for new link * @dentry: dentry for file * @mode: mode for creation * @dev_t: device associated with special file * */static intv9fs_vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev){	int retval;	char *name;	P9_DPRINTK(P9_DEBUG_VFS,		" %lu,%s mode: %x MAJOR: %u MINOR: %u\n", dir->i_ino,		dentry->d_name.name, mode, MAJOR(rdev), MINOR(rdev));	if (!new_valid_dev(rdev))		return -EINVAL;	name = __getname();	if (!name)		return -ENOMEM;	/* build extension */	if (S_ISBLK(mode))		sprintf(name, "b %u %u", MAJOR(rdev), MINOR(rdev));	else if (S_ISCHR(mode))		sprintf(name, "c %u %u", MAJOR(rdev), MINOR(rdev));	else if (S_ISFIFO(mode))		*name = 0;	else {		__putname(name);		return -EINVAL;	}	retval = v9fs_vfs_mkspecial(dir, dentry, mode, name);	__putname(name);	return retval;}static const struct inode_operations v9fs_dir_inode_operations_ext = {	.create = v9fs_vfs_create,	.lookup = v9fs_vfs_lookup,	.symlink = v9fs_vfs_symlink,	.link = v9fs_vfs_link,	.unlink = v9fs_vfs_unlink,	.mkdir = v9fs_vfs_mkdir,	.rmdir = v9fs_vfs_rmdir,	.mknod = v9fs_vfs_mknod,	.rename = v9fs_vfs_rename,	.readlink = v9fs_vfs_readlink,	.getattr = v9fs_vfs_getattr,	.setattr = v9fs_vfs_setattr,};static const struct inode_operations v9fs_dir_inode_operations = {	.create = v9fs_vfs_create,	.lookup = v9fs_vfs_lookup,	.unlink = v9fs_vfs_unlink,	.mkdir = v9fs_vfs_mkdir,	.rmdir = v9fs_vfs_rmdir,	.mknod = v9fs_vfs_mknod,	.rename = v9fs_vfs_rename,	.getattr = v9fs_vfs_getattr,	.setattr = v9fs_vfs_setattr,};static const struct inode_operations v9fs_file_inode_operations = {	.getattr = v9fs_vfs_getattr,	.setattr = v9fs_vfs_setattr,};static const struct inode_operations v9fs_symlink_inode_operations = {	.readlink = v9fs_vfs_readlink,	.follow_link = v9fs_vfs_follow_link,	.put_link = v9fs_vfs_put_link,	.getattr = v9fs_vfs_getattr,	.setattr = v9fs_vfs_setattr,};

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -