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

📄 unlink.c

📁 ARM 嵌入式 系统 设计与实例开发 实验教材 二源码
💻 C
字号:
/* *  linux/fs/nfs/unlink.c * * nfs sillydelete handling * * NOTE: we rely on holding the BKL for list manipulation protection. */#include <linux/slab.h>#include <linux/string.h>#include <linux/dcache.h>#include <linux/sunrpc/sched.h>#include <linux/sunrpc/clnt.h>#include <linux/nfs_fs.h>struct nfs_unlinkdata {	struct nfs_unlinkdata	*next;	struct dentry	*dir, *dentry;	struct qstr	name;	struct rpc_task	task;	struct rpc_cred	*cred;	unsigned int	count;};static struct nfs_unlinkdata	*nfs_deletes;static struct rpc_wait_queue	nfs_delete_queue = RPC_INIT_WAITQ("nfs_delete_queue");/** * nfs_detach_unlinkdata - Remove asynchronous unlink from global list * @data: pointer to descriptor */static inline voidnfs_detach_unlinkdata(struct nfs_unlinkdata *data){	struct nfs_unlinkdata	**q;	for (q = &nfs_deletes; *q != NULL; q = &((*q)->next)) {		if (*q == data) {			*q = data->next;			break;		}	}}/** * nfs_put_unlinkdata - release data from a sillydelete operation. * @data: pointer to unlink structure. */static voidnfs_put_unlinkdata(struct nfs_unlinkdata *data){	if (--data->count == 0) {		nfs_detach_unlinkdata(data);		if (data->name.name != NULL)			kfree(data->name.name);		kfree(data);	}}#define NAME_ALLOC_LEN(len)	((len+16) & ~15)/** * nfs_copy_dname - copy dentry name to data structure * @dentry: pointer to dentry * @data: nfs_unlinkdata */static inline voidnfs_copy_dname(struct dentry *dentry, struct nfs_unlinkdata *data){	char		*str;	int		len = dentry->d_name.len;	str = kmalloc(NAME_ALLOC_LEN(len), GFP_KERNEL);	if (!str)		return;	memcpy(str, dentry->d_name.name, len);	if (!data->name.len) {		data->name.len = len;		data->name.name = str;	} else		kfree(str);}/** * nfs_async_unlink_init - Initialize the RPC info * @task: rpc_task of the sillydelete * * We delay initializing RPC info until after the call to dentry_iput() * in order to minimize races against rename(). */static voidnfs_async_unlink_init(struct rpc_task *task){	struct nfs_unlinkdata	*data = (struct nfs_unlinkdata *)task->tk_calldata;	struct dentry		*dir = data->dir;	struct rpc_message	msg;	int			status = -ENOENT;	if (!data->name.len)		goto out_err;	memset(&msg, 0, sizeof(msg));	msg.rpc_cred = data->cred;	status = NFS_PROTO(dir->d_inode)->unlink_setup(&msg, dir, &data->name);	if (status < 0)		goto out_err;	rpc_call_setup(task, &msg, 0);	return; out_err:	rpc_exit(task, status);}/** * nfs_async_unlink_done - Sillydelete post-processing * @task: rpc_task of the sillydelete * * Do the directory attribute update. */static voidnfs_async_unlink_done(struct rpc_task *task){	struct nfs_unlinkdata	*data = (struct nfs_unlinkdata *)task->tk_calldata;	struct dentry		*dir = data->dir;	struct inode		*dir_i;	if (nfs_async_handle_jukebox(task))		return;	if (!dir)		return;	dir_i = dir->d_inode;	nfs_zap_caches(dir_i);	NFS_PROTO(dir_i)->unlink_done(dir, &task->tk_msg);	put_rpccred(data->cred);	data->cred = NULL;	dput(dir);}/** * nfs_async_unlink_release - Release the sillydelete data. * @task: rpc_task of the sillydelete * * We need to call nfs_put_unlinkdata as a 'tk_release' task since the * rpc_task would be freed too. */static voidnfs_async_unlink_release(struct rpc_task *task){	struct nfs_unlinkdata	*data = (struct nfs_unlinkdata *)task->tk_calldata;	nfs_put_unlinkdata(data);}/** * nfs_async_unlink - asynchronous unlinking of a file * @dir: directory in which the file resides. * @name: name of the file to unlink. */intnfs_async_unlink(struct dentry *dentry){	struct dentry	*dir = dentry->d_parent;	struct nfs_unlinkdata	*data;	struct rpc_task	*task;	struct rpc_clnt	*clnt = NFS_CLIENT(dir->d_inode);	int		status = -ENOMEM;	data = kmalloc(sizeof(*data), GFP_KERNEL);	if (!data)		goto out;	memset(data, 0, sizeof(*data));	data->dir = dget(dir);	data->dentry = dentry;	data->next = nfs_deletes;	nfs_deletes = data;	data->count = 1;	task = &data->task;	rpc_init_task(task, clnt, nfs_async_unlink_done , RPC_TASK_ASYNC);	task->tk_calldata = data;	task->tk_action = nfs_async_unlink_init;	task->tk_release = nfs_async_unlink_release;	dentry->d_flags |= DCACHE_NFSFS_RENAMED;	data->cred = rpcauth_lookupcred(clnt->cl_auth, 0);	rpc_sleep_on(&nfs_delete_queue, task, NULL, NULL);	status = 0; out:	return status;}/** * nfs_complete_remove - Initialize completion of the sillydelete * @dentry: dentry to delete * * Since we're most likely to be called by dentry_iput(), we * only use the dentry to find the sillydelete. We then copy the name * into the qstr. */voidnfs_complete_unlink(struct dentry *dentry){	struct nfs_unlinkdata	*data;	for(data = nfs_deletes; data != NULL; data = data->next) {		if (dentry == data->dentry)			break;	}	if (!data)		return;	data->count++;	nfs_copy_dname(dentry, data);	dentry->d_flags &= ~DCACHE_NFSFS_RENAMED;	if (data->task.tk_rpcwait == &nfs_delete_queue)		rpc_wake_up_task(&data->task);	nfs_put_unlinkdata(data);}

⌨️ 快捷键说明

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