1 /* 2 * linux/fs/nfs/unlink.c 3 * 4 * nfs sillydelete handling 5 * 6 */ 7 8 #include <linux/slab.h> 9 #include <linux/string.h> 10 #include <linux/dcache.h> 11 #include <linux/sunrpc/sched.h> 12 #include <linux/sunrpc/clnt.h> 13 #include <linux/nfs_fs.h> 14 15 16 struct nfs_unlinkdata { 17 struct nfs_removeargs args; 18 struct nfs_removeres res; 19 struct inode *dir; 20 struct rpc_cred *cred; 21 }; 22 23 /** 24 * nfs_free_unlinkdata - release data from a sillydelete operation. 25 * @data: pointer to unlink structure. 26 */ 27 static void 28 nfs_free_unlinkdata(struct nfs_unlinkdata *data) 29 { 30 iput(data->dir); 31 put_rpccred(data->cred); 32 kfree(data->args.name.name); 33 kfree(data); 34 } 35 36 #define NAME_ALLOC_LEN(len) ((len+16) & ~15) 37 /** 38 * nfs_copy_dname - copy dentry name to data structure 39 * @dentry: pointer to dentry 40 * @data: nfs_unlinkdata 41 */ 42 static int nfs_copy_dname(struct dentry *dentry, struct nfs_unlinkdata *data) 43 { 44 char *str; 45 int len = dentry->d_name.len; 46 47 str = kmemdup(dentry->d_name.name, NAME_ALLOC_LEN(len), GFP_KERNEL); 48 if (!str) 49 return -ENOMEM; 50 data->args.name.len = len; 51 data->args.name.name = str; 52 return 0; 53 } 54 55 /** 56 * nfs_async_unlink_init - Initialize the RPC info 57 * task: rpc_task of the sillydelete 58 */ 59 static void nfs_async_unlink_init(struct rpc_task *task, void *calldata) 60 { 61 struct nfs_unlinkdata *data = calldata; 62 struct inode *dir = data->dir; 63 struct rpc_message msg = { 64 .rpc_argp = &data->args, 65 .rpc_resp = &data->res, 66 .rpc_cred = data->cred, 67 }; 68 69 NFS_PROTO(dir)->unlink_setup(&msg, dir); 70 rpc_call_setup(task, &msg, 0); 71 } 72 73 /** 74 * nfs_async_unlink_done - Sillydelete post-processing 75 * @task: rpc_task of the sillydelete 76 * 77 * Do the directory attribute update. 78 */ 79 static void nfs_async_unlink_done(struct rpc_task *task, void *calldata) 80 { 81 struct nfs_unlinkdata *data = calldata; 82 struct inode *dir = data->dir; 83 84 if (!NFS_PROTO(dir)->unlink_done(task, dir)) 85 rpc_restart_call(task); 86 } 87 88 /** 89 * nfs_async_unlink_release - Release the sillydelete data. 90 * @task: rpc_task of the sillydelete 91 * 92 * We need to call nfs_put_unlinkdata as a 'tk_release' task since the 93 * rpc_task would be freed too. 94 */ 95 static void nfs_async_unlink_release(void *calldata) 96 { 97 struct nfs_unlinkdata *data = calldata; 98 nfs_free_unlinkdata(data); 99 } 100 101 static const struct rpc_call_ops nfs_unlink_ops = { 102 .rpc_call_prepare = nfs_async_unlink_init, 103 .rpc_call_done = nfs_async_unlink_done, 104 .rpc_release = nfs_async_unlink_release, 105 }; 106 107 static int nfs_call_unlink(struct dentry *dentry, struct nfs_unlinkdata *data) 108 { 109 struct rpc_task *task; 110 struct dentry *parent; 111 struct inode *dir; 112 113 if (nfs_copy_dname(dentry, data) < 0) 114 goto out_free; 115 116 parent = dget_parent(dentry); 117 if (parent == NULL) 118 goto out_free; 119 dir = igrab(parent->d_inode); 120 dput(parent); 121 if (dir == NULL) 122 goto out_free; 123 124 data->dir = dir; 125 data->args.fh = NFS_FH(dir); 126 nfs_fattr_init(&data->res.dir_attr); 127 128 task = rpc_run_task(NFS_CLIENT(dir), RPC_TASK_ASYNC, &nfs_unlink_ops, data); 129 if (!IS_ERR(task)) 130 rpc_put_task(task); 131 return 1; 132 out_free: 133 return 0; 134 } 135 136 /** 137 * nfs_async_unlink - asynchronous unlinking of a file 138 * @dir: parent directory of dentry 139 * @dentry: dentry to unlink 140 */ 141 int 142 nfs_async_unlink(struct inode *dir, struct dentry *dentry) 143 { 144 struct nfs_unlinkdata *data; 145 int status = -ENOMEM; 146 147 data = kzalloc(sizeof(*data), GFP_KERNEL); 148 if (data == NULL) 149 goto out; 150 151 data->cred = rpcauth_lookupcred(NFS_CLIENT(dir)->cl_auth, 0); 152 if (IS_ERR(data->cred)) { 153 status = PTR_ERR(data->cred); 154 goto out_free; 155 } 156 157 status = -EBUSY; 158 spin_lock(&dentry->d_lock); 159 if (dentry->d_flags & DCACHE_NFSFS_RENAMED) 160 goto out_unlock; 161 dentry->d_flags |= DCACHE_NFSFS_RENAMED; 162 dentry->d_fsdata = data; 163 spin_unlock(&dentry->d_lock); 164 return 0; 165 out_unlock: 166 spin_unlock(&dentry->d_lock); 167 put_rpccred(data->cred); 168 out_free: 169 kfree(data); 170 out: 171 return status; 172 } 173 174 /** 175 * nfs_complete_unlink - Initialize completion of the sillydelete 176 * @dentry: dentry to delete 177 * @inode: inode 178 * 179 * Since we're most likely to be called by dentry_iput(), we 180 * only use the dentry to find the sillydelete. We then copy the name 181 * into the qstr. 182 */ 183 void 184 nfs_complete_unlink(struct dentry *dentry, struct inode *inode) 185 { 186 struct nfs_unlinkdata *data = NULL; 187 188 spin_lock(&dentry->d_lock); 189 if (dentry->d_flags & DCACHE_NFSFS_RENAMED) { 190 dentry->d_flags &= ~DCACHE_NFSFS_RENAMED; 191 data = dentry->d_fsdata; 192 } 193 spin_unlock(&dentry->d_lock); 194 195 if (data != NULL && (NFS_STALE(inode) || !nfs_call_unlink(dentry, data))) 196 nfs_free_unlinkdata(data); 197 } 198