linux/fs/nfs/unlink.c
<<
>>
Prefs
   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#include <linux/sched.h>
  15#include <linux/wait.h>
  16#include <linux/namei.h>
  17
  18#include "internal.h"
  19#include "nfs4_fs.h"
  20#include "iostat.h"
  21#include "delegation.h"
  22
  23/**
  24 * nfs_free_unlinkdata - release data from a sillydelete operation.
  25 * @data: pointer to unlink structure.
  26 */
  27static void
  28nfs_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 */
  42static 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
  55static void nfs_free_dname(struct nfs_unlinkdata *data)
  56{
  57        kfree(data->args.name.name);
  58        data->args.name.name = NULL;
  59        data->args.name.len = 0;
  60}
  61
  62static void nfs_dec_sillycount(struct inode *dir)
  63{
  64        struct nfs_inode *nfsi = NFS_I(dir);
  65        if (atomic_dec_return(&nfsi->silly_count) == 1)
  66                wake_up(&nfsi->waitqueue);
  67}
  68
  69/**
  70 * nfs_async_unlink_done - Sillydelete post-processing
  71 * @task: rpc_task of the sillydelete
  72 *
  73 * Do the directory attribute update.
  74 */
  75static void nfs_async_unlink_done(struct rpc_task *task, void *calldata)
  76{
  77        struct nfs_unlinkdata *data = calldata;
  78        struct inode *dir = data->dir;
  79
  80        if (!NFS_PROTO(dir)->unlink_done(task, dir))
  81                rpc_restart_call_prepare(task);
  82}
  83
  84/**
  85 * nfs_async_unlink_release - Release the sillydelete data.
  86 * @task: rpc_task of the sillydelete
  87 *
  88 * We need to call nfs_put_unlinkdata as a 'tk_release' task since the
  89 * rpc_task would be freed too.
  90 */
  91static void nfs_async_unlink_release(void *calldata)
  92{
  93        struct nfs_unlinkdata   *data = calldata;
  94        struct super_block *sb = data->dir->i_sb;
  95
  96        nfs_dec_sillycount(data->dir);
  97        nfs_free_unlinkdata(data);
  98        nfs_sb_deactive(sb);
  99}
 100
 101static void nfs_unlink_prepare(struct rpc_task *task, void *calldata)
 102{
 103        struct nfs_unlinkdata *data = calldata;
 104        NFS_PROTO(data->dir)->unlink_rpc_prepare(task, data);
 105}
 106
 107static const struct rpc_call_ops nfs_unlink_ops = {
 108        .rpc_call_done = nfs_async_unlink_done,
 109        .rpc_release = nfs_async_unlink_release,
 110        .rpc_call_prepare = nfs_unlink_prepare,
 111};
 112
 113static int nfs_do_call_unlink(struct dentry *parent, struct inode *dir, struct nfs_unlinkdata *data)
 114{
 115        struct rpc_message msg = {
 116                .rpc_argp = &data->args,
 117                .rpc_resp = &data->res,
 118                .rpc_cred = data->cred,
 119        };
 120        struct rpc_task_setup task_setup_data = {
 121                .rpc_message = &msg,
 122                .callback_ops = &nfs_unlink_ops,
 123                .callback_data = data,
 124                .workqueue = nfsiod_workqueue,
 125                .flags = RPC_TASK_ASYNC,
 126        };
 127        struct rpc_task *task;
 128        struct dentry *alias;
 129
 130        alias = d_lookup(parent, &data->args.name);
 131        if (alias != NULL) {
 132                int ret;
 133                void *devname_garbage = NULL;
 134
 135                /*
 136                 * Hey, we raced with lookup... See if we need to transfer
 137                 * the sillyrename information to the aliased dentry.
 138                 */
 139                nfs_free_dname(data);
 140                ret = nfs_copy_dname(alias, data);
 141                spin_lock(&alias->d_lock);
 142                if (ret == 0 && alias->d_inode != NULL &&
 143                    !(alias->d_flags & DCACHE_NFSFS_RENAMED)) {
 144                        devname_garbage = alias->d_fsdata;
 145                        alias->d_fsdata = data;
 146                        alias->d_flags |= DCACHE_NFSFS_RENAMED;
 147                        ret = 1;
 148                } else
 149                        ret = 0;
 150                spin_unlock(&alias->d_lock);
 151                nfs_dec_sillycount(dir);
 152                dput(alias);
 153                /*
 154                 * If we'd displaced old cached devname, free it.  At that
 155                 * point dentry is definitely not a root, so we won't need
 156                 * that anymore.
 157                 */
 158                kfree(devname_garbage);
 159                return ret;
 160        }
 161        data->dir = igrab(dir);
 162        if (!data->dir) {
 163                nfs_dec_sillycount(dir);
 164                return 0;
 165        }
 166        nfs_sb_active(dir->i_sb);
 167        data->args.fh = NFS_FH(dir);
 168        nfs_fattr_init(data->res.dir_attr);
 169
 170        NFS_PROTO(dir)->unlink_setup(&msg, dir);
 171
 172        task_setup_data.rpc_client = NFS_CLIENT(dir);
 173        task = rpc_run_task(&task_setup_data);
 174        if (!IS_ERR(task))
 175                rpc_put_task_async(task);
 176        return 1;
 177}
 178
 179static int nfs_call_unlink(struct dentry *dentry, struct nfs_unlinkdata *data)
 180{
 181        struct dentry *parent;
 182        struct inode *dir;
 183        int ret = 0;
 184
 185
 186        parent = dget_parent(dentry);
 187        if (parent == NULL)
 188                goto out_free;
 189        dir = parent->d_inode;
 190        /* Non-exclusive lock protects against concurrent lookup() calls */
 191        spin_lock(&dir->i_lock);
 192        if (atomic_inc_not_zero(&NFS_I(dir)->silly_count) == 0) {
 193                /* Deferred delete */
 194                hlist_add_head(&data->list, &NFS_I(dir)->silly_list);
 195                spin_unlock(&dir->i_lock);
 196                ret = 1;
 197                goto out_dput;
 198        }
 199        spin_unlock(&dir->i_lock);
 200        ret = nfs_do_call_unlink(parent, dir, data);
 201out_dput:
 202        dput(parent);
 203out_free:
 204        return ret;
 205}
 206
 207void nfs_block_sillyrename(struct dentry *dentry)
 208{
 209        struct nfs_inode *nfsi = NFS_I(dentry->d_inode);
 210
 211        wait_event(nfsi->waitqueue, atomic_cmpxchg(&nfsi->silly_count, 1, 0) == 1);
 212}
 213
 214void nfs_unblock_sillyrename(struct dentry *dentry)
 215{
 216        struct inode *dir = dentry->d_inode;
 217        struct nfs_inode *nfsi = NFS_I(dir);
 218        struct nfs_unlinkdata *data;
 219
 220        atomic_inc(&nfsi->silly_count);
 221        spin_lock(&dir->i_lock);
 222        while (!hlist_empty(&nfsi->silly_list)) {
 223                if (!atomic_inc_not_zero(&nfsi->silly_count))
 224                        break;
 225                data = hlist_entry(nfsi->silly_list.first, struct nfs_unlinkdata, list);
 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);
 230                spin_lock(&dir->i_lock);
 231        }
 232        spin_unlock(&dir->i_lock);
 233}
 234
 235/**
 236 * nfs_async_unlink - asynchronous unlinking of a file
 237 * @dir: parent directory of dentry
 238 * @dentry: dentry to unlink
 239 */
 240static int
 241nfs_async_unlink(struct inode *dir, struct dentry *dentry)
 242{
 243        struct nfs_unlinkdata *data;
 244        int status = -ENOMEM;
 245        void *devname_garbage = NULL;
 246
 247        data = kzalloc(sizeof(*data), GFP_KERNEL);
 248        if (data == NULL)
 249                goto out;
 250
 251        data->cred = rpc_lookup_cred();
 252        if (IS_ERR(data->cred)) {
 253                status = PTR_ERR(data->cred);
 254                goto out_free;
 255        }
 256        data->res.dir_attr = &data->dir_attr;
 257
 258        status = -EBUSY;
 259        spin_lock(&dentry->d_lock);
 260        if (dentry->d_flags & DCACHE_NFSFS_RENAMED)
 261                goto out_unlock;
 262        dentry->d_flags |= DCACHE_NFSFS_RENAMED;
 263        devname_garbage = dentry->d_fsdata;
 264        dentry->d_fsdata = data;
 265        spin_unlock(&dentry->d_lock);
 266        /*
 267         * If we'd displaced old cached devname, free it.  At that
 268         * point dentry is definitely not a root, so we won't need
 269         * that anymore.
 270         */
 271        if (devname_garbage)
 272                kfree(devname_garbage);
 273        return 0;
 274out_unlock:
 275        spin_unlock(&dentry->d_lock);
 276        put_rpccred(data->cred);
 277out_free:
 278        kfree(data);
 279out:
 280        return status;
 281}
 282
 283/**
 284 * nfs_complete_unlink - Initialize completion of the sillydelete
 285 * @dentry: dentry to delete
 286 * @inode: inode
 287 *
 288 * Since we're most likely to be called by dentry_iput(), we
 289 * only use the dentry to find the sillydelete. We then copy the name
 290 * into the qstr.
 291 */
 292void
 293nfs_complete_unlink(struct dentry *dentry, struct inode *inode)
 294{
 295        struct nfs_unlinkdata   *data = NULL;
 296
 297        spin_lock(&dentry->d_lock);
 298        if (dentry->d_flags & DCACHE_NFSFS_RENAMED) {
 299                dentry->d_flags &= ~DCACHE_NFSFS_RENAMED;
 300                data = dentry->d_fsdata;
 301                dentry->d_fsdata = NULL;
 302        }
 303        spin_unlock(&dentry->d_lock);
 304
 305        if (data != NULL && (NFS_STALE(inode) || !nfs_call_unlink(dentry, data)))
 306                nfs_free_unlinkdata(data);
 307}
 308
 309/* Cancel a queued async unlink. Called when a sillyrename run fails. */
 310static void
 311nfs_cancel_async_unlink(struct dentry *dentry)
 312{
 313        spin_lock(&dentry->d_lock);
 314        if (dentry->d_flags & DCACHE_NFSFS_RENAMED) {
 315                struct nfs_unlinkdata *data = dentry->d_fsdata;
 316
 317                dentry->d_flags &= ~DCACHE_NFSFS_RENAMED;
 318                dentry->d_fsdata = NULL;
 319                spin_unlock(&dentry->d_lock);
 320                nfs_free_unlinkdata(data);
 321                return;
 322        }
 323        spin_unlock(&dentry->d_lock);
 324}
 325
 326/**
 327 * nfs_async_rename_done - Sillyrename post-processing
 328 * @task: rpc_task of the sillyrename
 329 * @calldata: nfs_renamedata for the sillyrename
 330 *
 331 * Do the directory attribute updates and the d_move
 332 */
 333static void nfs_async_rename_done(struct rpc_task *task, void *calldata)
 334{
 335        struct nfs_renamedata *data = calldata;
 336        struct inode *old_dir = data->old_dir;
 337        struct inode *new_dir = data->new_dir;
 338        struct dentry *old_dentry = data->old_dentry;
 339        struct dentry *new_dentry = data->new_dentry;
 340
 341        if (!NFS_PROTO(old_dir)->rename_done(task, old_dir, new_dir)) {
 342                rpc_restart_call_prepare(task);
 343                return;
 344        }
 345
 346        if (task->tk_status != 0) {
 347                nfs_cancel_async_unlink(old_dentry);
 348                return;
 349        }
 350
 351        d_drop(old_dentry);
 352        d_drop(new_dentry);
 353}
 354
 355/**
 356 * nfs_async_rename_release - Release the sillyrename data.
 357 * @calldata: the struct nfs_renamedata to be released
 358 */
 359static void nfs_async_rename_release(void *calldata)
 360{
 361        struct nfs_renamedata   *data = calldata;
 362        struct super_block *sb = data->old_dir->i_sb;
 363
 364        if (data->old_dentry->d_inode)
 365                nfs_mark_for_revalidate(data->old_dentry->d_inode);
 366
 367        dput(data->old_dentry);
 368        dput(data->new_dentry);
 369        iput(data->old_dir);
 370        iput(data->new_dir);
 371        nfs_sb_deactive(sb);
 372        put_rpccred(data->cred);
 373        kfree(data);
 374}
 375
 376static void nfs_rename_prepare(struct rpc_task *task, void *calldata)
 377{
 378        struct nfs_renamedata *data = calldata;
 379        NFS_PROTO(data->old_dir)->rename_rpc_prepare(task, data);
 380}
 381
 382static const struct rpc_call_ops nfs_rename_ops = {
 383        .rpc_call_done = nfs_async_rename_done,
 384        .rpc_release = nfs_async_rename_release,
 385        .rpc_call_prepare = nfs_rename_prepare,
 386};
 387
 388/**
 389 * nfs_async_rename - perform an asynchronous rename operation
 390 * @old_dir: directory that currently holds the dentry to be renamed
 391 * @new_dir: target directory for the rename
 392 * @old_dentry: original dentry to be renamed
 393 * @new_dentry: dentry to which the old_dentry should be renamed
 394 *
 395 * It's expected that valid references to the dentries and inodes are held
 396 */
 397static struct rpc_task *
 398nfs_async_rename(struct inode *old_dir, struct inode *new_dir,
 399                 struct dentry *old_dentry, struct dentry *new_dentry)
 400{
 401        struct nfs_renamedata *data;
 402        struct rpc_message msg = { };
 403        struct rpc_task_setup task_setup_data = {
 404                .rpc_message = &msg,
 405                .callback_ops = &nfs_rename_ops,
 406                .workqueue = nfsiod_workqueue,
 407                .rpc_client = NFS_CLIENT(old_dir),
 408                .flags = RPC_TASK_ASYNC,
 409        };
 410
 411        data = kzalloc(sizeof(*data), GFP_KERNEL);
 412        if (data == NULL)
 413                return ERR_PTR(-ENOMEM);
 414        task_setup_data.callback_data = data;
 415
 416        data->cred = rpc_lookup_cred();
 417        if (IS_ERR(data->cred)) {
 418                struct rpc_task *task = ERR_CAST(data->cred);
 419                kfree(data);
 420                return task;
 421        }
 422
 423        msg.rpc_argp = &data->args;
 424        msg.rpc_resp = &data->res;
 425        msg.rpc_cred = data->cred;
 426
 427        /* set up nfs_renamedata */
 428        data->old_dir = old_dir;
 429        ihold(old_dir);
 430        data->new_dir = new_dir;
 431        ihold(new_dir);
 432        data->old_dentry = dget(old_dentry);
 433        data->new_dentry = dget(new_dentry);
 434        nfs_fattr_init(&data->old_fattr);
 435        nfs_fattr_init(&data->new_fattr);
 436
 437        /* set up nfs_renameargs */
 438        data->args.old_dir = NFS_FH(old_dir);
 439        data->args.old_name = &old_dentry->d_name;
 440        data->args.new_dir = NFS_FH(new_dir);
 441        data->args.new_name = &new_dentry->d_name;
 442
 443        /* set up nfs_renameres */
 444        data->res.old_fattr = &data->old_fattr;
 445        data->res.new_fattr = &data->new_fattr;
 446
 447        nfs_sb_active(old_dir->i_sb);
 448
 449        NFS_PROTO(data->old_dir)->rename_setup(&msg, old_dir);
 450
 451        return rpc_run_task(&task_setup_data);
 452}
 453
 454/**
 455 * nfs_sillyrename - Perform a silly-rename of a dentry
 456 * @dir: inode of directory that contains dentry
 457 * @dentry: dentry to be sillyrenamed
 458 *
 459 * NFSv2/3 is stateless and the server doesn't know when the client is
 460 * holding a file open. To prevent application problems when a file is
 461 * unlinked while it's still open, the client performs a "silly-rename".
 462 * That is, it renames the file to a hidden file in the same directory,
 463 * and only performs the unlink once the last reference to it is put.
 464 *
 465 * The final cleanup is done during dentry_iput.
 466 *
 467 * (Note: NFSv4 is stateful, and has opens, so in theory an NFSv4 server
 468 * could take responsibility for keeping open files referenced.  The server
 469 * would also need to ensure that opened-but-deleted files were kept over
 470 * reboots.  However, we may not assume a server does so.  (RFC 5661
 471 * does provide an OPEN4_RESULT_PRESERVE_UNLINKED flag that a server can
 472 * use to advertise that it does this; some day we may take advantage of
 473 * it.))
 474 */
 475int
 476nfs_sillyrename(struct inode *dir, struct dentry *dentry)
 477{
 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;
 482        char           silly[slen+1];
 483        struct dentry *sdentry;
 484        struct rpc_task *task;
 485        int            error = -EIO;
 486
 487        dfprintk(VFS, "NFS: silly-rename(%s/%s, ct=%d)\n",
 488                dentry->d_parent->d_name.name, dentry->d_name.name,
 489                dentry->d_count);
 490        nfs_inc_stats(dir, NFSIOS_SILLYRENAME);
 491
 492        /*
 493         * We don't allow a dentry to be silly-renamed twice.
 494         */
 495        error = -EBUSY;
 496        if (dentry->d_flags & DCACHE_NFSFS_RENAMED)
 497                goto out;
 498
 499        sprintf(silly, ".nfs%*.*Lx",
 500                fileidsize, fileidsize,
 501                (unsigned long long)NFS_FILEID(dentry->d_inode));
 502
 503        /* Return delegation in anticipation of the rename */
 504        NFS_PROTO(dentry->d_inode)->return_delegation(dentry->d_inode);
 505
 506        sdentry = NULL;
 507        do {
 508                char *suffix = silly + slen - countersize;
 509
 510                dput(sdentry);
 511                sillycounter++;
 512                sprintf(suffix, "%*.*x", countersize, countersize, sillycounter);
 513
 514                dfprintk(VFS, "NFS: trying to rename %s to %s\n",
 515                                dentry->d_name.name, silly);
 516
 517                sdentry = lookup_one_len(silly, dentry->d_parent, slen);
 518                /*
 519                 * N.B. Better to return EBUSY here ... it could be
 520                 * dangerous to delete the file while it's in use.
 521                 */
 522                if (IS_ERR(sdentry))
 523                        goto out;
 524        } while (sdentry->d_inode != NULL); /* need negative lookup */
 525
 526        /* queue unlink first. Can't do this from rpc_release as it
 527         * has to allocate memory
 528         */
 529        error = nfs_async_unlink(dir, dentry);
 530        if (error)
 531                goto out_dput;
 532
 533        /* populate unlinkdata with the right dname */
 534        error = nfs_copy_dname(sdentry,
 535                                (struct nfs_unlinkdata *)dentry->d_fsdata);
 536        if (error) {
 537                nfs_cancel_async_unlink(dentry);
 538                goto out_dput;
 539        }
 540
 541        /* run the rename task, undo unlink if it fails */
 542        task = nfs_async_rename(dir, dir, dentry, sdentry);
 543        if (IS_ERR(task)) {
 544                error = -EBUSY;
 545                nfs_cancel_async_unlink(dentry);
 546                goto out_dput;
 547        }
 548
 549        /* wait for the RPC task to complete, unless a SIGKILL intervenes */
 550        error = rpc_wait_for_completion_task(task);
 551        if (error == 0)
 552                error = task->tk_status;
 553        rpc_put_task(task);
 554out_dput:
 555        dput(sdentry);
 556out:
 557        return error;
 558}
 559
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.