// SPDX-License-Identifier: GPL-2.0-or-later /* AFS silly rename handling * * Copyright (C) 2019 Red Hat, Inc. All Rights Reserved. * Written by David Howells (dhowells@redhat.com) * - Derived from NFS's sillyrename.
*/
/* * Perform silly-rename of a dentry. * * AFS is stateless and the server doesn't know when the client is holding a * file open. To prevent application problems when a file is unlinked while * it's still open, the client performs a "silly-rename". That is, it renames * the file to a hidden file in the same directory, and only performs the * unlink once the last reference to it is put. * * The final cleanup is done during dentry_iput.
*/ int afs_sillyrename(struct afs_vnode *dvnode, struct afs_vnode *vnode, struct dentry *dentry, struct key *key)
{ staticunsignedint sillycounter; struct dentry *sdentry = NULL; unsignedchar silly[16]; int ret = -EBUSY;
_enter("");
/* We don't allow a dentry to be silly-renamed twice. */ if (dentry->d_flags & DCACHE_NFSFS_RENAMED) return -EBUSY;
sdentry = NULL; do {
dput(sdentry);
sillycounter++;
/* Create a silly name. Note that the ".__afs" prefix is * understood by the salvager and must not be changed.
*/
scnprintf(silly, sizeof(silly), ".__afs%04X", sillycounter);
sdentry = lookup_noperm(&QSTR(silly), dentry->d_parent);
/* N.B. Better to return EBUSY here ... it could be dangerous * to delete the file while it's in use.
*/ if (IS_ERR(sdentry)) goto out;
} while (!d_is_negative(sdentry));
ihold(&vnode->netfs.inode);
ret = afs_do_silly_rename(dvnode, vnode, dentry, sdentry, key); switch (ret) { case 0: /* The rename succeeded. */
set_bit(AFS_VNODE_SILLY_DELETED, &vnode->flags);
d_move(dentry, sdentry); break; case -ERESTARTSYS: /* The result of the rename is unknown. Play it safe by forcing * a new lookup.
*/
d_drop(dentry);
d_drop(sdentry);
}
/* If there was a conflict with a third party, check the status of the * unlinked vnode.
*/ if (op->cumul_error.error == 0 && (op->flags & AFS_OPERATION_DIR_CONFLICT)) {
op->file[1].update_ctime = false;
op->fetch_status.which = 1;
op->ops = &afs_fetch_status_operation;
afs_begin_vnode_operation(op);
afs_wait_for_operation(op);
}
alias = d_alloc_parallel(dentry->d_parent, &dentry->d_name, &wq); if (IS_ERR(alias)) {
up_read(&dvnode->rmdir_lock); return 0;
}
if (!d_in_lookup(alias)) { /* We raced with lookup... See if we need to transfer the * sillyrename information to the aliased dentry.
*/
ret = 0;
spin_lock(&alias->d_lock); if (d_really_is_positive(alias) &&
!(alias->d_flags & DCACHE_NFSFS_RENAMED)) {
alias->d_flags |= DCACHE_NFSFS_RENAMED;
ret = 1;
}
spin_unlock(&alias->d_lock);
up_read(&dvnode->rmdir_lock);
dput(alias); return ret;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.