8 #include <linux/slab.h>
9 #include <linux/string.h>
13 #include <linux/nfs_fs.h>
14 #include <linux/sched.h>
15 #include <linux/wait.h>
36 #define NAME_ALLOC_LEN(len) ((len+16) & ~15)
50 data->
args.name.len = len;
59 data->
args.name.len = 0;
62 static void nfs_dec_sillycount(
struct inode *dir)
75 static void nfs_async_unlink_done(
struct rpc_task *
task,
void *calldata)
80 if (!NFS_PROTO(dir)->unlink_done(task, dir))
91 static void nfs_async_unlink_release(
void *calldata)
96 nfs_dec_sillycount(data->
dir);
97 nfs_free_unlinkdata(data);
101 static void nfs_unlink_prepare(
struct rpc_task *task,
void *calldata)
104 NFS_PROTO(data->
dir)->unlink_rpc_prepare(task, data);
108 .rpc_call_done = nfs_async_unlink_done,
109 .rpc_release = nfs_async_unlink_release,
110 .rpc_call_prepare = nfs_unlink_prepare,
116 .rpc_argp = &data->
args,
117 .rpc_resp = &data->
res,
118 .rpc_cred = data->
cred,
122 .callback_ops = &nfs_unlink_ops,
123 .callback_data =
data,
133 void *devname_garbage =
NULL;
139 nfs_free_dname(data);
140 ret = nfs_copy_dname(alias, data);
141 spin_lock(&alias->
d_lock);
150 spin_unlock(&alias->
d_lock);
151 nfs_dec_sillycount(dir);
158 kfree(devname_garbage);
163 nfs_dec_sillycount(dir);
167 data->
args.fh = NFS_FH(dir);
170 NFS_PROTO(dir)->unlink_setup(&msg, dir);
181 struct dentry *parent;
194 hlist_add_head(&data->
list, &NFS_I(dir)->silly_list);
195 spin_unlock(&dir->
i_lock);
199 spin_unlock(&dir->
i_lock);
200 ret = nfs_do_call_unlink(parent, dir, data);
226 hlist_del(&data->
list);
227 spin_unlock(&dir->
i_lock);
228 if (nfs_do_call_unlink(dentry, dir, data) == 0)
229 nfs_free_unlinkdata(data);
232 spin_unlock(&dir->
i_lock);
241 nfs_async_unlink(
struct inode *dir,
struct dentry *dentry)
245 void *devname_garbage =
NULL;
252 if (IS_ERR(data->
cred)) {
253 status = PTR_ERR(data->
cred);
259 spin_lock(&dentry->
d_lock);
265 spin_unlock(&dentry->
d_lock);
272 kfree(devname_garbage);
275 spin_unlock(&dentry->
d_lock);
297 spin_lock(&dentry->
d_lock);
303 spin_unlock(&dentry->
d_lock);
305 if (data !=
NULL && (NFS_STALE(inode) || !nfs_call_unlink(dentry, data)))
306 nfs_free_unlinkdata(data);
311 nfs_cancel_async_unlink(
struct dentry *dentry)
313 spin_lock(&dentry->
d_lock);
319 spin_unlock(&dentry->
d_lock);
320 nfs_free_unlinkdata(data);
323 spin_unlock(&dentry->
d_lock);
333 static void nfs_async_rename_done(
struct rpc_task *task,
void *calldata)
341 if (!NFS_PROTO(old_dir)->rename_done(task, old_dir, new_dir)) {
347 nfs_cancel_async_unlink(old_dentry);
359 static void nfs_async_rename_release(
void *calldata)
365 nfs_mark_for_revalidate(data->
old_dentry->d_inode);
376 static void nfs_rename_prepare(
struct rpc_task *task,
void *calldata)
379 NFS_PROTO(data->
old_dir)->rename_rpc_prepare(task, data);
383 .rpc_call_done = nfs_async_rename_done,
384 .rpc_release = nfs_async_rename_release,
385 .rpc_call_prepare = nfs_rename_prepare,
398 nfs_async_rename(
struct inode *old_dir,
struct inode *new_dir,
399 struct dentry *old_dentry,
struct dentry *new_dentry)
405 .callback_ops = &nfs_rename_ops,
407 .rpc_client = NFS_CLIENT(old_dir),
417 if (IS_ERR(data->
cred)) {
438 data->
args.old_dir = NFS_FH(old_dir);
440 data->
args.new_dir = NFS_FH(new_dir);
449 NFS_PROTO(data->
old_dir)->rename_setup(&msg, old_dir);
478 static unsigned int sillycounter;
479 const int fileidsize =
sizeof(NFS_FILEID(dentry->
d_inode))*2;
480 const int countersize =
sizeof(sillycounter)*2;
481 const int slen =
sizeof(
".nfs")+fileidsize+countersize-1;
483 struct dentry *sdentry;
487 dfprintk(VFS,
"NFS: silly-rename(%s/%s, ct=%d)\n",
500 fileidsize, fileidsize,
501 (
unsigned long long)NFS_FILEID(dentry->
d_inode));
508 char *suffix = silly + slen - countersize;
512 sprintf(suffix,
"%*.*x", countersize, countersize, sillycounter);
514 dfprintk(VFS,
"NFS: trying to rename %s to %s\n",
515 dentry->
d_name.name, silly);
529 error = nfs_async_unlink(dir, dentry);
534 error = nfs_copy_dname(sdentry,
537 nfs_cancel_async_unlink(dentry);
542 task = nfs_async_rename(dir, dir, dentry, sdentry);
545 nfs_cancel_async_unlink(dentry);
550 error = rpc_wait_for_completion_task(task);