File: /usr/src/linux/fs/nfs/unlink.c

1     /*
2      *  linux/fs/nfs/unlink.c
3      *
4      * nfs sillydelete handling
5      *
6      * NOTE: we rely on holding the BKL for list manipulation protection.
7      */
8     
9     #include <linux/slab.h>
10     #include <linux/string.h>
11     #include <linux/dcache.h>
12     #include <linux/sunrpc/sched.h>
13     #include <linux/sunrpc/clnt.h>
14     #include <linux/nfs_fs.h>
15     
16     
17     struct nfs_unlinkdata {
18     	struct nfs_unlinkdata	*next;
19     	struct dentry	*dir, *dentry;
20     	struct qstr	name;
21     	struct rpc_task	task;
22     	struct rpc_cred	*cred;
23     	unsigned int	count;
24     };
25     
26     static struct nfs_unlinkdata	*nfs_deletes;
27     static struct rpc_wait_queue	nfs_delete_queue = RPC_INIT_WAITQ("nfs_delete_queue");
28     
29     /**
30      * nfs_detach_unlinkdata - Remove asynchronous unlink from global list
31      * @data: pointer to descriptor
32      */
33     static inline void
34     nfs_detach_unlinkdata(struct nfs_unlinkdata *data)
35     {
36     	struct nfs_unlinkdata	**q;
37     
38     	for (q = &nfs_deletes; *q != NULL; q = &((*q)->next)) {
39     		if (*q == data) {
40     			*q = data->next;
41     			break;
42     		}
43     	}
44     }
45     
46     /**
47      * nfs_put_unlinkdata - release data from a sillydelete operation.
48      * @data: pointer to unlink structure.
49      */
50     static void
51     nfs_put_unlinkdata(struct nfs_unlinkdata *data)
52     {
53     	if (--data->count == 0) {
54     		nfs_detach_unlinkdata(data);
55     		if (data->name.name != NULL)
56     			kfree(data->name.name);
57     		kfree(data);
58     	}
59     }
60     
61     #define NAME_ALLOC_LEN(len)	((len+16) & ~15)
62     /**
63      * nfs_copy_dname - copy dentry name to data structure
64      * @dentry: pointer to dentry
65      * @data: nfs_unlinkdata
66      */
67     static inline void
68     nfs_copy_dname(struct dentry *dentry, struct nfs_unlinkdata *data)
69     {
70     	char		*str;
71     	int		len = dentry->d_name.len;
72     
73     	str = kmalloc(NAME_ALLOC_LEN(len), GFP_KERNEL);
74     	if (!str)
75     		return;
76     	memcpy(str, dentry->d_name.name, len);
77     	if (!data->name.len) {
78     		data->name.len = len;
79     		data->name.name = str;
80     	} else
81     		kfree(str);
82     }
83     
84     /**
85      * nfs_async_unlink_init - Initialize the RPC info
86      * @task: rpc_task of the sillydelete
87      *
88      * We delay initializing RPC info until after the call to dentry_iput()
89      * in order to minimize races against rename().
90      */
91     static void
92     nfs_async_unlink_init(struct rpc_task *task)
93     {
94     	struct nfs_unlinkdata	*data = (struct nfs_unlinkdata *)task->tk_calldata;
95     	struct dentry		*dir = data->dir;
96     	struct rpc_message	msg;
97     	int			status = -ENOENT;
98     
99     	if (!data->name.len)
100     		goto out_err;
101     
102     	memset(&msg, 0, sizeof(msg));
103     	msg.rpc_cred = data->cred;
104     	status = NFS_PROTO(dir->d_inode)->unlink_setup(&msg, dir, &data->name);
105     	if (status < 0)
106     		goto out_err;
107     	rpc_call_setup(task, &msg, 0);
108     	return;
109      out_err:
110     	rpc_exit(task, status);
111     }
112     
113     /**
114      * nfs_async_unlink_done - Sillydelete post-processing
115      * @task: rpc_task of the sillydelete
116      *
117      * Do the directory attribute update.
118      */
119     static void
120     nfs_async_unlink_done(struct rpc_task *task)
121     {
122     	struct nfs_unlinkdata	*data = (struct nfs_unlinkdata *)task->tk_calldata;
123     	struct dentry		*dir = data->dir;
124     	struct inode		*dir_i;
125     
126     	if (!dir)
127     		return;
128     	dir_i = dir->d_inode;
129     	nfs_zap_caches(dir_i);
130     	NFS_PROTO(dir_i)->unlink_done(dir, &task->tk_msg);
131     	put_rpccred(data->cred);
132     	data->cred = NULL;
133     	dput(dir);
134     }
135     
136     /**
137      * nfs_async_unlink_release - Release the sillydelete data.
138      * @task: rpc_task of the sillydelete
139      *
140      * We need to call nfs_put_unlinkdata as a 'tk_release' task since the
141      * rpc_task would be freed too.
142      */
143     static void
144     nfs_async_unlink_release(struct rpc_task *task)
145     {
146     	struct nfs_unlinkdata	*data = (struct nfs_unlinkdata *)task->tk_calldata;
147     	nfs_put_unlinkdata(data);
148     }
149     
150     /**
151      * nfs_async_unlink - asynchronous unlinking of a file
152      * @dir: directory in which the file resides.
153      * @name: name of the file to unlink.
154      */
155     int
156     nfs_async_unlink(struct dentry *dentry)
157     {
158     	struct dentry	*dir = dentry->d_parent;
159     	struct nfs_unlinkdata	*data;
160     	struct rpc_task	*task;
161     	struct rpc_clnt	*clnt = NFS_CLIENT(dir->d_inode);
162     	int		status = -ENOMEM;
163     
164     	data = kmalloc(sizeof(*data), GFP_KERNEL);
165     	if (!data)
166     		goto out;
167     	memset(data, 0, sizeof(*data));
168     
169     	data->dir = dget(dir);
170     	data->dentry = dentry;
171     
172     	data->next = nfs_deletes;
173     	nfs_deletes = data;
174     	data->count = 1;
175     
176     	task = &data->task;
177     	rpc_init_task(task, clnt, nfs_async_unlink_done , RPC_TASK_ASYNC);
178     	task->tk_calldata = data;
179     	task->tk_action = nfs_async_unlink_init;
180     	task->tk_release = nfs_async_unlink_release;
181     
182     	dentry->d_flags |= DCACHE_NFSFS_RENAMED;
183     	data->cred = rpcauth_lookupcred(clnt->cl_auth, 0);
184     
185     	rpc_sleep_on(&nfs_delete_queue, task, NULL, NULL);
186     	status = 0;
187      out:
188     	return status;
189     }
190     
191     /**
192      * nfs_complete_remove - Initialize completion of the sillydelete
193      * @dentry: dentry to delete
194      *
195      * Since we're most likely to be called by dentry_iput(), we
196      * only use the dentry to find the sillydelete. We then copy the name
197      * into the qstr.
198      */
199     void
200     nfs_complete_unlink(struct dentry *dentry)
201     {
202     	struct nfs_unlinkdata	*data;
203     
204     	for(data = nfs_deletes; data != NULL; data = data->next) {
205     		if (dentry == data->dentry)
206     			break;
207     	}
208     	if (!data)
209     		return;
210     	data->count++;
211     	nfs_copy_dname(dentry, data);
212     	dentry->d_flags &= ~DCACHE_NFSFS_RENAMED;
213     	if (data->task.tk_rpcwait == &nfs_delete_queue)
214     		rpc_wake_up_task(&data->task);
215     	nfs_put_unlinkdata(data);
216     }
217