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

📄 dir.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	vnode = AFS_FS_I(dentry->d_inode);	if (dentry->d_inode)		_enter("{v={%x:%u} n=%s fl=%lx},",		       vnode->fid.vid, vnode->fid.vnode, dentry->d_name.name,		       vnode->flags);	else		_enter("{neg n=%s}", dentry->d_name.name);	key = afs_request_key(AFS_FS_S(dentry->d_sb)->volume->cell);	if (IS_ERR(key))		key = NULL;	/* lock down the parent dentry so we can peer at it */	parent = dget_parent(dentry);	if (!parent->d_inode)		goto out_bad;	dir = AFS_FS_I(parent->d_inode);	/* validate the parent directory */	if (test_bit(AFS_VNODE_MODIFIED, &dir->flags))		afs_validate(dir, key);	if (test_bit(AFS_VNODE_DELETED, &dir->flags)) {		_debug("%s: parent dir deleted", dentry->d_name.name);		goto out_bad;	}	dir_version = (void *) (unsigned long) dir->status.data_version;	if (dentry->d_fsdata == dir_version)		goto out_valid; /* the dir contents are unchanged */	_debug("dir modified");	/* search the directory for this vnode */	ret = afs_do_lookup(&dir->vfs_inode, dentry, &fid, key);	switch (ret) {	case 0:		/* the filename maps to something */		if (!dentry->d_inode)			goto out_bad;		if (is_bad_inode(dentry->d_inode)) {			printk("kAFS: afs_d_revalidate: %s/%s has bad inode\n",			       parent->d_name.name, dentry->d_name.name);			goto out_bad;		}		/* if the vnode ID has changed, then the dirent points to a		 * different file */		if (fid.vnode != vnode->fid.vnode) {			_debug("%s: dirent changed [%u != %u]",			       dentry->d_name.name, fid.vnode,			       vnode->fid.vnode);			goto not_found;		}		/* if the vnode ID uniqifier has changed, then the file has		 * been deleted and replaced, and the original vnode ID has		 * been reused */		if (fid.unique != vnode->fid.unique) {			_debug("%s: file deleted (uq %u -> %u I:%lu)",			       dentry->d_name.name, fid.unique,			       vnode->fid.unique, dentry->d_inode->i_version);			spin_lock(&vnode->lock);			set_bit(AFS_VNODE_DELETED, &vnode->flags);			spin_unlock(&vnode->lock);			goto not_found;		}		goto out_valid;	case -ENOENT:		/* the filename is unknown */		_debug("%s: dirent not found", dentry->d_name.name);		if (dentry->d_inode)			goto not_found;		goto out_valid;	default:		_debug("failed to iterate dir %s: %d",		       parent->d_name.name, ret);		goto out_bad;	}out_valid:	dentry->d_fsdata = dir_version;out_skip:	dput(parent);	key_put(key);	_leave(" = 1 [valid]");	return 1;	/* the dirent, if it exists, now points to a different vnode */not_found:	spin_lock(&dentry->d_lock);	dentry->d_flags |= DCACHE_NFSFS_RENAMED;	spin_unlock(&dentry->d_lock);out_bad:	if (dentry->d_inode) {		/* don't unhash if we have submounts */		if (have_submounts(dentry))			goto out_skip;	}	_debug("dropping dentry %s/%s",	       parent->d_name.name, dentry->d_name.name);	shrink_dcache_parent(dentry);	d_drop(dentry);	dput(parent);	key_put(key);	_leave(" = 0 [bad]");	return 0;}/* * allow the VFS to enquire as to whether a dentry should be unhashed (mustn't * sleep) * - called from dput() when d_count is going to 0. * - return 1 to request dentry be unhashed, 0 otherwise */static int afs_d_delete(struct dentry *dentry){	_enter("%s", dentry->d_name.name);	if (dentry->d_flags & DCACHE_NFSFS_RENAMED)		goto zap;	if (dentry->d_inode &&	    test_bit(AFS_VNODE_DELETED, &AFS_FS_I(dentry->d_inode)->flags))			goto zap;	_leave(" = 0 [keep]");	return 0;zap:	_leave(" = 1 [zap]");	return 1;}/* * handle dentry release */static void afs_d_release(struct dentry *dentry){	_enter("%s", dentry->d_name.name);}/* * create a directory on an AFS filesystem */static int afs_mkdir(struct inode *dir, struct dentry *dentry, int mode){	struct afs_file_status status;	struct afs_callback cb;	struct afs_server *server;	struct afs_vnode *dvnode, *vnode;	struct afs_fid fid;	struct inode *inode;	struct key *key;	int ret;	dvnode = AFS_FS_I(dir);	_enter("{%x:%u},{%s},%o",	       dvnode->fid.vid, dvnode->fid.vnode, dentry->d_name.name, mode);	ret = -ENAMETOOLONG;	if (dentry->d_name.len >= AFSNAMEMAX)		goto error;	key = afs_request_key(dvnode->volume->cell);	if (IS_ERR(key)) {		ret = PTR_ERR(key);		goto error;	}	mode |= S_IFDIR;	ret = afs_vnode_create(dvnode, key, dentry->d_name.name,			       mode, &fid, &status, &cb, &server);	if (ret < 0)		goto mkdir_error;	inode = afs_iget(dir->i_sb, key, &fid, &status, &cb);	if (IS_ERR(inode)) {		/* ENOMEM at a really inconvenient time - just abandon the new		 * directory on the server */		ret = PTR_ERR(inode);		goto iget_error;	}	/* apply the status report we've got for the new vnode */	vnode = AFS_FS_I(inode);	spin_lock(&vnode->lock);	vnode->update_cnt++;	spin_unlock(&vnode->lock);	afs_vnode_finalise_status_update(vnode, server);	afs_put_server(server);	d_instantiate(dentry, inode);	if (d_unhashed(dentry)) {		_debug("not hashed");		d_rehash(dentry);	}	key_put(key);	_leave(" = 0");	return 0;iget_error:	afs_put_server(server);mkdir_error:	key_put(key);error:	d_drop(dentry);	_leave(" = %d", ret);	return ret;}/* * remove a directory from an AFS filesystem */static int afs_rmdir(struct inode *dir, struct dentry *dentry){	struct afs_vnode *dvnode, *vnode;	struct key *key;	int ret;	dvnode = AFS_FS_I(dir);	_enter("{%x:%u},{%s}",	       dvnode->fid.vid, dvnode->fid.vnode, dentry->d_name.name);	ret = -ENAMETOOLONG;	if (dentry->d_name.len >= AFSNAMEMAX)		goto error;	key = afs_request_key(dvnode->volume->cell);	if (IS_ERR(key)) {		ret = PTR_ERR(key);		goto error;	}	ret = afs_vnode_remove(dvnode, key, dentry->d_name.name, true);	if (ret < 0)		goto rmdir_error;	if (dentry->d_inode) {		vnode = AFS_FS_I(dentry->d_inode);		clear_nlink(&vnode->vfs_inode);		set_bit(AFS_VNODE_DELETED, &vnode->flags);		afs_discard_callback_on_delete(vnode);	}	key_put(key);	_leave(" = 0");	return 0;rmdir_error:	key_put(key);error:	_leave(" = %d", ret);	return ret;}/* * remove a file from an AFS filesystem */static int afs_unlink(struct inode *dir, struct dentry *dentry){	struct afs_vnode *dvnode, *vnode;	struct key *key;	int ret;	dvnode = AFS_FS_I(dir);	_enter("{%x:%u},{%s}",	       dvnode->fid.vid, dvnode->fid.vnode, dentry->d_name.name);	ret = -ENAMETOOLONG;	if (dentry->d_name.len >= AFSNAMEMAX)		goto error;	key = afs_request_key(dvnode->volume->cell);	if (IS_ERR(key)) {		ret = PTR_ERR(key);		goto error;	}	if (dentry->d_inode) {		vnode = AFS_FS_I(dentry->d_inode);		/* make sure we have a callback promise on the victim */		ret = afs_validate(vnode, key);		if (ret < 0)			goto error;	}	ret = afs_vnode_remove(dvnode, key, dentry->d_name.name, false);	if (ret < 0)		goto remove_error;	if (dentry->d_inode) {		/* if the file wasn't deleted due to excess hard links, the		 * fileserver will break the callback promise on the file - if		 * it had one - before it returns to us, and if it was deleted,		 * it won't		 *		 * however, if we didn't have a callback promise outstanding,		 * or it was outstanding on a different server, then it won't		 * break it either...		 */		vnode = AFS_FS_I(dentry->d_inode);		if (test_bit(AFS_VNODE_DELETED, &vnode->flags))			_debug("AFS_VNODE_DELETED");		if (test_bit(AFS_VNODE_CB_BROKEN, &vnode->flags))			_debug("AFS_VNODE_CB_BROKEN");		set_bit(AFS_VNODE_CB_BROKEN, &vnode->flags);		ret = afs_validate(vnode, key);		_debug("nlink %d [val %d]", vnode->vfs_inode.i_nlink, ret);	}	key_put(key);	_leave(" = 0");	return 0;remove_error:	key_put(key);error:	_leave(" = %d", ret);	return ret;}/* * create a regular file on an AFS filesystem */static int afs_create(struct inode *dir, struct dentry *dentry, int mode,		      struct nameidata *nd){	struct afs_file_status status;	struct afs_callback cb;	struct afs_server *server;	struct afs_vnode *dvnode, *vnode;	struct afs_fid fid;	struct inode *inode;	struct key *key;	int ret;	dvnode = AFS_FS_I(dir);	_enter("{%x:%u},{%s},%o,",	       dvnode->fid.vid, dvnode->fid.vnode, dentry->d_name.name, mode);	ret = -ENAMETOOLONG;	if (dentry->d_name.len >= AFSNAMEMAX)		goto error;	key = afs_request_key(dvnode->volume->cell);	if (IS_ERR(key)) {		ret = PTR_ERR(key);		goto error;	}	mode |= S_IFREG;	ret = afs_vnode_create(dvnode, key, dentry->d_name.name,			       mode, &fid, &status, &cb, &server);	if (ret < 0)		goto create_error;	inode = afs_iget(dir->i_sb, key, &fid, &status, &cb);	if (IS_ERR(inode)) {		/* ENOMEM at a really inconvenient time - just abandon the new		 * directory on the server */		ret = PTR_ERR(inode);		goto iget_error;	}	/* apply the status report we've got for the new vnode */	vnode = AFS_FS_I(inode);	spin_lock(&vnode->lock);	vnode->update_cnt++;	spin_unlock(&vnode->lock);	afs_vnode_finalise_status_update(vnode, server);	afs_put_server(server);	d_instantiate(dentry, inode);	if (d_unhashed(dentry)) {		_debug("not hashed");		d_rehash(dentry);	}	key_put(key);	_leave(" = 0");	return 0;iget_error:	afs_put_server(server);create_error:	key_put(key);error:	d_drop(dentry);	_leave(" = %d", ret);	return ret;}/* * create a hard link between files in an AFS filesystem */static int afs_link(struct dentry *from, struct inode *dir,		    struct dentry *dentry){	struct afs_vnode *dvnode, *vnode;	struct key *key;	int ret;	vnode = AFS_FS_I(from->d_inode);	dvnode = AFS_FS_I(dir);	_enter("{%x:%u},{%x:%u},{%s}",	       vnode->fid.vid, vnode->fid.vnode,	       dvnode->fid.vid, dvnode->fid.vnode,	       dentry->d_name.name);	ret = -ENAMETOOLONG;	if (dentry->d_name.len >= AFSNAMEMAX)		goto error;	key = afs_request_key(dvnode->volume->cell);	if (IS_ERR(key)) {		ret = PTR_ERR(key);		goto error;	}	ret = afs_vnode_link(dvnode, vnode, key, dentry->d_name.name);	if (ret < 0)		goto link_error;	atomic_inc(&vnode->vfs_inode.i_count);	d_instantiate(dentry, &vnode->vfs_inode);	key_put(key);	_leave(" = 0");	return 0;link_error:	key_put(key);error:	d_drop(dentry);	_leave(" = %d", ret);	return ret;}/* * create a symlink in an AFS filesystem */static int afs_symlink(struct inode *dir, struct dentry *dentry,		       const char *content){	struct afs_file_status status;	struct afs_server *server;	struct afs_vnode *dvnode, *vnode;	struct afs_fid fid;	struct inode *inode;	struct key *key;	int ret;	dvnode = AFS_FS_I(dir);	_enter("{%x:%u},{%s},%s",	       dvnode->fid.vid, dvnode->fid.vnode, dentry->d_name.name,	       content);	ret = -ENAMETOOLONG;	if (dentry->d_name.len >= AFSNAMEMAX)		goto error;	ret = -EINVAL;	if (strlen(content) >= AFSPATHMAX)		goto error;	key = afs_request_key(dvnode->volume->cell);	if (IS_ERR(key)) {		ret = PTR_ERR(key);		goto error;	}	ret = afs_vnode_symlink(dvnode, key, dentry->d_name.name, content,				&fid, &status, &server);	if (ret < 0)		goto create_error;	inode = afs_iget(dir->i_sb, key, &fid, &status, NULL);	if (IS_ERR(inode)) {		/* ENOMEM at a really inconvenient time - just abandon the new		 * directory on the server */		ret = PTR_ERR(inode);		goto iget_error;	}	/* apply the status report we've got for the new vnode */	vnode = AFS_FS_I(inode);	spin_lock(&vnode->lock);	vnode->update_cnt++;	spin_unlock(&vnode->lock);	afs_vnode_finalise_status_update(vnode, server);	afs_put_server(server);	d_instantiate(dentry, inode);	if (d_unhashed(dentry)) {		_debug("not hashed");		d_rehash(dentry);	}	key_put(key);	_leave(" = 0");	return 0;iget_error:	afs_put_server(server);create_error:	key_put(key);error:	d_drop(dentry);	_leave(" = %d", ret);	return ret;}/* * rename a file in an AFS filesystem and/or move it between directories */static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,		      struct inode *new_dir, struct dentry *new_dentry){	struct afs_vnode *orig_dvnode, *new_dvnode, *vnode;	struct key *key;	int ret;	vnode = AFS_FS_I(old_dentry->d_inode);	orig_dvnode = AFS_FS_I(old_dir);	new_dvnode = AFS_FS_I(new_dir);	_enter("{%x:%u},{%x:%u},{%x:%u},{%s}",	       orig_dvnode->fid.vid, orig_dvnode->fid.vnode,	       vnode->fid.vid, vnode->fid.vnode,	       new_dvnode->fid.vid, new_dvnode->fid.vnode,	       new_dentry->d_name.name);	ret = -ENAMETOOLONG;	if (new_dentry->d_name.len >= AFSNAMEMAX)		goto error;	key = afs_request_key(orig_dvnode->volume->cell);	if (IS_ERR(key)) {		ret = PTR_ERR(key);		goto error;	}	ret = afs_vnode_rename(orig_dvnode, new_dvnode, key,			       old_dentry->d_name.name,			       new_dentry->d_name.name);	if (ret < 0)		goto rename_error;	key_put(key);	_leave(" = 0");	return 0;rename_error:	key_put(key);error:	d_drop(new_dentry);	_leave(" = %d", ret);	return ret;}

⌨️ 快捷键说明

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