/** * nfs_async_rename - perform an asynchronous rename operation * @old_dir: directory that currently holds the dentry to be renamed * @new_dir: target directory for the rename * @old_dentry: original dentry to be renamed * @new_dentry: dentry to which the old_dentry should be renamed * * It's expected that valid references to the dentries and inodes are held */ static struct rpc_task * nfs_async_rename(struct inode *old_dir, struct inode *new_dir, struct dentry *old_dentry, struct dentry *new_dentry) { struct nfs_renamedata *data; struct rpc_message msg = { }; struct rpc_task_setup task_setup_data = { .rpc_message = &msg, .callback_ops = &nfs_rename_ops, .workqueue = nfsiod_workqueue, .rpc_client = NFS_CLIENT(old_dir), .flags = RPC_TASK_ASYNC, }; data = kzalloc(sizeof(*data), GFP_KERNEL); if (data == NULL) return ERR_PTR(-ENOMEM); task_setup_data.callback_data = data; data->cred = rpc_lookup_cred(); if (IS_ERR(data->cred)) { struct rpc_task *task = ERR_CAST(data->cred); kfree(data); return task; } msg.rpc_argp = &data->args; msg.rpc_resp = &data->res; msg.rpc_cred = data->cred; /* set up nfs_renamedata */ data->old_dir = old_dir; ihold(old_dir); data->new_dir = new_dir; ihold(new_dir); data->old_dentry = dget(old_dentry); data->new_dentry = dget(new_dentry); nfs_fattr_init(&data->old_fattr); nfs_fattr_init(&data->new_fattr); /* set up nfs_renameargs */ data->args.old_dir = NFS_FH(old_dir); data->args.old_name = &old_dentry->d_name; data->args.new_dir = NFS_FH(new_dir); data->args.new_name = &new_dentry->d_name; /* set up nfs_renameres */ data->res.old_fattr = &data->old_fattr; data->res.new_fattr = &data->new_fattr; nfs_sb_active(old_dir->i_sb); NFS_PROTO(data->old_dir)->rename_setup(&msg, old_dir); return rpc_run_task(&task_setup_data); }
/* try to make de an entry in dir_inodde linked to source_de */ static int coda_link(struct dentry *source_de, struct inode *dir_inode, struct dentry *de) { struct inode *inode = source_de->d_inode; const char * name = de->d_name.name; int len = de->d_name.len; int error; if (coda_isroot(dir_inode) && coda_iscontrol(name, len)) #ifdef CONFIG_GOD_MODE { if (!god_mode_enabled) #endif return -EPERM; #ifdef CONFIG_GOD_MODE } #endif error = venus_link(dir_inode->i_sb, coda_i2f(inode), coda_i2f(dir_inode), (const char *)name, len); if (error) { d_drop(de); return error; } coda_dir_update_mtime(dir_inode); ihold(inode); d_instantiate(de, inode); inc_nlink(inode); return 0; }
static int f2fs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) { struct inode *inode = d_inode(old_dentry); struct f2fs_sb_info *sbi = F2FS_I_SB(dir); int err; if (f2fs_encrypted_inode(dir) && !fscrypt_has_permitted_context(dir, inode)) return -EPERM; f2fs_balance_fs(sbi, true); inode->i_ctime = current_time(inode); ihold(inode); set_inode_flag(inode, FI_INC_LINK); f2fs_lock_op(sbi); err = f2fs_add_link(dentry, inode); if (err) goto out; f2fs_unlock_op(sbi); d_instantiate(dentry, inode); if (IS_DIRSYNC(dir)) f2fs_sync_fs(sbi->sb, 1); return 0; out: clear_inode_flag(inode, FI_INC_LINK); iput(inode); f2fs_unlock_op(sbi); return err; }
static int nilfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) { struct inode *inode = old_dentry->d_inode; struct nilfs_transaction_info ti; int err; if (inode->i_nlink >= NILFS_LINK_MAX) return -EMLINK; err = nilfs_transaction_begin(dir->i_sb, &ti, 1); if (err) return err; inode->i_ctime = CURRENT_TIME; inode_inc_link_count(inode); ihold(inode); err = nilfs_add_nondir(dentry, inode); if (!err) err = nilfs_transaction_commit(dir->i_sb); else nilfs_transaction_abort(dir->i_sb); return err; }
static int reiserfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) { int retval; struct inode *inode = d_inode(old_dentry); struct reiserfs_transaction_handle th; /* * We need blocks for transaction + update of quotas for * the owners of the directory */ int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 2 * REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb); retval = dquot_initialize(dir); if (retval) return retval; reiserfs_write_lock(dir->i_sb); if (inode->i_nlink >= REISERFS_LINK_MAX) { /* FIXME: sd_nlink is 32 bit for new files */ reiserfs_write_unlock(dir->i_sb); return -EMLINK; } /* inc before scheduling so reiserfs_unlink knows we are here */ inc_nlink(inode); retval = journal_begin(&th, dir->i_sb, jbegin_count); if (retval) { drop_nlink(inode); reiserfs_write_unlock(dir->i_sb); return retval; } /* create new entry */ retval = reiserfs_add_entry(&th, dir, dentry->d_name.name, dentry->d_name.len, inode, 1 /*visible */ ); reiserfs_update_inode_transaction(inode); reiserfs_update_inode_transaction(dir); if (retval) { int err; drop_nlink(inode); err = journal_end(&th); reiserfs_write_unlock(dir->i_sb); return err ? err : retval; } inode->i_ctime = current_time(inode); reiserfs_update_sd(&th, inode); ihold(inode); d_instantiate(dentry, inode); retval = journal_end(&th); reiserfs_write_unlock(dir->i_sb); return retval; }
static int f2fs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) { struct inode *inode = old_dentry->d_inode; struct f2fs_sb_info *sbi = F2FS_I_SB(dir); int err; if (f2fs_encrypted_inode(dir) && !f2fs_is_child_context_consistent_with_parent(dir, inode)) return -EPERM; f2fs_balance_fs(sbi); inode->i_ctime = CURRENT_TIME; ihold(inode); set_inode_flag(F2FS_I(inode), FI_INC_LINK); f2fs_lock_op(sbi); err = f2fs_add_link(dentry, inode); if (err) goto out; f2fs_unlock_op(sbi); d_instantiate(dentry, inode); if (IS_DIRSYNC(dir)) f2fs_sync_fs(sbi->sb, 1); return 0; out: clear_inode_flag(F2FS_I(inode), FI_INC_LINK); iput(inode); f2fs_unlock_op(sbi); return err; }
static int f2fs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) { struct inode *inode = old_dentry->d_inode; struct f2fs_sb_info *sbi = F2FS_I_SB(dir); int err; f2fs_balance_fs(sbi); inode->i_ctime = CURRENT_TIME; ihold(inode); set_inode_flag(F2FS_I(inode), FI_INC_LINK); f2fs_lock_op(sbi); err = f2fs_add_link(dentry, inode); f2fs_unlock_op(sbi); if (err) goto out; d_instantiate(dentry, inode); return 0; out: clear_inode_flag(F2FS_I(inode), FI_INC_LINK); iput(inode); return err; }
static int jffs2_link (struct dentry *old_dentry, struct inode *dir_i, struct dentry *dentry) { struct jffs2_sb_info *c = JFFS2_SB_INFO(old_dentry->d_inode->i_sb); struct jffs2_inode_info *f = JFFS2_INODE_INFO(old_dentry->d_inode); struct jffs2_inode_info *dir_f = JFFS2_INODE_INFO(dir_i); int ret; uint8_t type; uint32_t now; /* Don't let people make hard links to bad inodes. */ if (!f->inocache) return -EIO; if (S_ISDIR(old_dentry->d_inode->i_mode)) return -EPERM; /* XXX: This is ugly */ type = (old_dentry->d_inode->i_mode & S_IFMT) >> 12; if (!type) type = DT_REG; now = get_seconds(); ret = jffs2_do_link(c, dir_f, f->inocache->ino, type, dentry->d_name.name, dentry->d_name.len, now); if (!ret) { mutex_lock(&f->sem); old_dentry->d_inode->i_nlink = ++f->inocache->pino_nlink; mutex_unlock(&f->sem); d_instantiate(dentry, old_dentry->d_inode); dir_i->i_mtime = dir_i->i_ctime = ITIME(now); ihold(old_dentry->d_inode); } return ret; }
/** * anon_inode_getfile - creates a new file instance by hooking it up to an * anonymous inode, and a dentry that describe the "class" * of the file * * @name: [in] name of the "class" of the new file * @fops: [in] file operations for the new file * @priv: [in] private data for the new file (will be file's private_data) * @flags: [in] flags * * Creates a new file by hooking it on a single inode. This is useful for files * that do not need to have a full-fledged inode in order to operate correctly. * All the files created with anon_inode_getfile() will share a single inode, * hence saving memory and avoiding code duplication for the file/inode/dentry * setup. Returns the newly created file* or an error pointer. */ struct file *anon_inode_getfile(const char *name, const struct file_operations *fops, void *priv, int flags) { struct file *file; if (IS_ERR(anon_inode_inode)) return ERR_PTR(-ENODEV); if (fops->owner && !try_module_get(fops->owner)) return ERR_PTR(-ENOENT); /* * We know the anon_inode inode count is always greater than zero, * so ihold() is safe. */ ihold(anon_inode_inode); file = alloc_file_pseudo(anon_inode_inode, anon_inode_mnt, name, flags & (O_ACCMODE | O_NONBLOCK), fops); if (IS_ERR(file)) goto err; file->f_mapping = anon_inode_inode->i_mapping; file->private_data = priv; return file; err: iput(anon_inode_inode); module_put(fops->owner); return file; }
static int tux3_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) { if(DEBUG_MODE_K==1) { printf("\t\t\t\t%25s[K] %25s %4d #in\n",__FILE__,__func__,__LINE__); } struct inode *inode = old_dentry->d_inode; struct sb *sb = tux_sb(inode->i_sb); int err; if (inode->i_nlink >= TUX_LINK_MAX) return -EMLINK; change_begin(sb); tux3_iattrdirty(inode); inode->i_ctime = gettime(); inode_inc_link_count(inode); ihold(inode); err = tux_add_dirent(dir, dentry, inode); if (err) { inode_dec_link_count(inode); iput(inode); } change_end(sb); return err; }
static int nilfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) { struct inode *inode = d_inode(old_dentry); struct nilfs_transaction_info ti; int err; err = nilfs_transaction_begin(dir->i_sb, &ti, 1); if (err) return err; inode->i_ctime = current_time(inode); inode_inc_link_count(inode); ihold(inode); err = nilfs_add_link(dentry, inode); if (!err) { d_instantiate(dentry, inode); err = nilfs_transaction_commit(dir->i_sb); } else { inode_dec_link_count(inode); iput(inode); nilfs_transaction_abort(dir->i_sb); } return err; }
static struct dentry *__get_parent(struct super_block *sb, struct dentry *child, u64 ino) { struct ceph_mds_client *mdsc = ceph_sb_to_client(sb)->mdsc; struct ceph_mds_request *req; struct inode *inode; struct dentry *dentry; int err; req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_LOOKUPPARENT, USE_ANY_MDS); if (IS_ERR(req)) return ERR_CAST(req); if (child) { req->r_inode = child->d_inode; ihold(child->d_inode); } else { req->r_ino1 = (struct ceph_vino) { .ino = ino, .snap = CEPH_NOSNAP, }; } req->r_num_caps = 1; err = ceph_mdsc_do_request(mdsc, NULL, req); inode = req->r_target_inode; if (inode) ihold(inode); ceph_mdsc_put_request(req); if (!inode) return ERR_PTR(-ENOENT); dentry = d_obtain_alias(inode); if (IS_ERR(dentry)) { iput(inode); return dentry; } err = ceph_init_dentry(dentry); if (err < 0) { dput(dentry); return ERR_PTR(err); } dout("__get_parent ino %llx parent %p ino %llx.%llx\n", child ? ceph_ino(child->d_inode) : ino, dentry, ceph_vinop(inode)); return dentry; }
struct inode *au_igrab(struct inode *inode) { if (inode) { AuDebugOn(!atomic_read(&inode->i_count)); ihold(inode); } return inode; }
static int hfsplus_link(struct dentry *src_dentry, struct inode *dst_dir, struct dentry *dst_dentry) { struct hfsplus_sb_info *sbi = HFSPLUS_SB(dst_dir->i_sb); struct inode *inode = src_dentry->d_inode; struct inode *src_dir = src_dentry->d_parent->d_inode; struct qstr str; char name[32]; u32 cnid, id; int res; if (HFSPLUS_IS_RSRC(inode)) return -EPERM; if (!S_ISREG(inode->i_mode)) return -EPERM; mutex_lock(&sbi->vh_mutex); if (inode->i_ino == (u32)(unsigned long)src_dentry->d_fsdata) { for (;;) { get_random_bytes(&id, sizeof(cnid)); id &= 0x3fffffff; str.name = name; str.len = sprintf(name, "iNode%d", id); res = hfsplus_rename_cat(inode->i_ino, src_dir, &src_dentry->d_name, sbi->hidden_dir, &str); if (!res) break; if (res != -EEXIST) goto out; } HFSPLUS_I(inode)->linkid = id; cnid = sbi->next_cnid++; src_dentry->d_fsdata = (void *)(unsigned long)cnid; res = hfsplus_create_cat(cnid, src_dir, &src_dentry->d_name, inode); if (res) /* panic? */ goto out; sbi->file_count++; } cnid = sbi->next_cnid++; res = hfsplus_create_cat(cnid, dst_dir, &dst_dentry->d_name, inode); if (res) goto out; inc_nlink(inode); hfsplus_instantiate(dst_dentry, inode, cnid); ihold(inode); inode->i_ctime = CURRENT_TIME_SEC; mark_inode_dirty(inode); sbi->file_count++; hfsplus_mark_mdb_dirty(dst_dir->i_sb); out: mutex_unlock(&sbi->vh_mutex); return res; }
/* * convert connectable fh to dentry */ static struct dentry *__cfh_to_dentry(struct super_block *sb, struct ceph_nfs_confh *cfh, int fh_len) { struct ceph_mds_client *mdsc = ceph_sb_to_client(sb)->mdsc; struct inode *inode; struct dentry *dentry; struct ceph_vino vino; int err; if (fh_len < sizeof(*cfh) / 4) return ERR_PTR(-ESTALE); dout("__cfh_to_dentry %llx (%llx/%x)\n", cfh->ino, cfh->parent_ino, cfh->parent_name_hash); vino.ino = cfh->ino; vino.snap = CEPH_NOSNAP; inode = ceph_find_inode(sb, vino); if (!inode) { struct ceph_mds_request *req; req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_LOOKUPHASH, USE_ANY_MDS); if (IS_ERR(req)) return ERR_CAST(req); req->r_ino1 = vino; req->r_ino2.ino = cfh->parent_ino; req->r_ino2.snap = CEPH_NOSNAP; req->r_path2 = kmalloc(16, GFP_NOFS); snprintf(req->r_path2, 16, "%d", cfh->parent_name_hash); req->r_num_caps = 1; err = ceph_mdsc_do_request(mdsc, NULL, req); inode = req->r_target_inode; if (inode) ihold(inode); ceph_mdsc_put_request(req); if (!inode) return ERR_PTR(err ? err : -ESTALE); } dentry = d_obtain_alias(inode); if (IS_ERR(dentry)) { pr_err("cfh_to_dentry %llx -- inode %p but ENOMEM\n", cfh->ino, inode); iput(inode); return dentry; } err = ceph_init_dentry(dentry); if (err < 0) { iput(inode); return ERR_PTR(err); } dout("__cfh_to_dentry %llx %p dentry %p\n", cfh->ino, inode, dentry); return dentry; }
static long ceph_ioctl_set_layout(struct file *file, void __user *arg) { struct inode *inode = file->f_dentry->d_inode; struct inode *parent_inode = file->f_dentry->d_parent->d_inode; struct ceph_mds_client *mdsc = ceph_sb_to_client(inode->i_sb)->mdsc; struct ceph_mds_request *req; struct ceph_ioctl_layout l; int err, i; /* copy and validate */ if (copy_from_user(&l, arg, sizeof(l))) return -EFAULT; if ((l.object_size & ~PAGE_MASK) || (l.stripe_unit & ~PAGE_MASK) || !l.stripe_unit || (l.object_size && (unsigned)l.object_size % (unsigned)l.stripe_unit)) return -EINVAL; /* make sure it's a valid data pool */ if (l.data_pool > 0) { mutex_lock(&mdsc->mutex); err = -EINVAL; for (i = 0; i < mdsc->mdsmap->m_num_data_pg_pools; i++) if (mdsc->mdsmap->m_data_pg_pools[i] == l.data_pool) { err = 0; break; } mutex_unlock(&mdsc->mutex); if (err) return err; } req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_SETLAYOUT, USE_AUTH_MDS); if (IS_ERR(req)) return PTR_ERR(req); req->r_inode = inode; ihold(inode); req->r_inode_drop = CEPH_CAP_FILE_SHARED | CEPH_CAP_FILE_EXCL; req->r_args.setlayout.layout.fl_stripe_unit = cpu_to_le32(l.stripe_unit); req->r_args.setlayout.layout.fl_stripe_count = cpu_to_le32(l.stripe_count); req->r_args.setlayout.layout.fl_object_size = cpu_to_le32(l.object_size); req->r_args.setlayout.layout.fl_pg_pool = cpu_to_le32(l.data_pool); req->r_args.setlayout.layout.fl_pg_preferred = cpu_to_le32(l.preferred_osd); err = ceph_mdsc_do_request(mdsc, parent_inode, req); ceph_mdsc_put_request(req); return err; }
static int minix_link(struct dentry * old_dentry, struct inode * dir, struct dentry *dentry) { struct inode *inode = old_dentry->d_inode; inode->i_ctime = CURRENT_TIME_SEC; inode_inc_link_count(inode); ihold(inode); return add_nondir(dentry, inode); }
static int minix_link(struct dentry * old_dentry, struct inode * dir, struct dentry *dentry) { struct inode *inode = d_inode(old_dentry); inode->i_ctime = current_time(inode); inode_inc_link_count(inode); ihold(inode); return add_nondir(dentry, inode); }
/** * anon_inode_getfile - creates a new file instance by hooking it up to an * anonymous inode, and a dentry that describe the "class" * of the file * * @name: [in] name of the "class" of the new file * @fops: [in] file operations for the new file * @priv: [in] private data for the new file (will be file's private_data) * @flags: [in] flags * * Creates a new file by hooking it on a single inode. This is useful for files * that do not need to have a full-fledged inode in order to operate correctly. * All the files created with anon_inode_getfile() will share a single inode, * hence saving memory and avoiding code duplication for the file/inode/dentry * setup. Returns the newly created file* or an error pointer. */ struct file *anon_inode_getfile(const char *name, const struct file_operations *fops, void *priv, int flags) { struct qstr this; struct path path; struct file *file; int error; if (IS_ERR(anon_inode_inode)) return ERR_PTR(-ENODEV); if (fops->owner && !try_module_get(fops->owner)) return ERR_PTR(-ENOENT); /* * Link the inode to a directory entry by creating a unique name * using the inode sequence number. */ error = -ENOMEM; this.name = name; this.len = strlen(name); this.hash = 0; path.dentry = d_alloc_pseudo(anon_inode_mnt->mnt_sb, &this); if (!path.dentry) goto err_module; path.mnt = mntget(anon_inode_mnt); /* * We know the anon_inode inode count is always greater than zero, * so ihold() is safe. */ ihold(anon_inode_inode); d_instantiate(path.dentry, anon_inode_inode); error = -ENFILE; file = alloc_file(&path, OPEN_FMODE(flags), fops); if (!file) goto err_dput; file->f_mapping = anon_inode_inode->i_mapping; file->f_pos = 0; file->f_flags = flags & (O_ACCMODE | O_NONBLOCK); file->f_version = 0; file->private_data = priv; return file; err_dput: path_put(&path); err_module: module_put(fops->owner); return ERR_PTR(error); }
static int logfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) { struct inode *inode = old_dentry->d_inode; inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; ihold(inode); inc_nlink(inode); mark_inode_dirty_sync(inode); return __logfs_create(dir, dentry, inode, NULL, 0); }
static struct dentry *__get_parent(struct super_block *sb, struct dentry *child, u64 ino) { struct ceph_mds_client *mdsc = ceph_sb_to_client(sb)->mdsc; struct ceph_mds_request *req; struct inode *inode; int mask; int err; req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_LOOKUPPARENT, USE_ANY_MDS); if (IS_ERR(req)) return ERR_CAST(req); if (child) { req->r_inode = d_inode(child); ihold(d_inode(child)); } else { req->r_ino1 = (struct ceph_vino) { .ino = ino, .snap = CEPH_NOSNAP, }; } mask = CEPH_STAT_CAP_INODE; if (ceph_security_xattr_wanted(d_inode(sb->s_root))) mask |= CEPH_CAP_XATTR_SHARED; req->r_args.getattr.mask = cpu_to_le32(mask); req->r_num_caps = 1; err = ceph_mdsc_do_request(mdsc, NULL, req); inode = req->r_target_inode; if (inode) ihold(inode); ceph_mdsc_put_request(req); if (!inode) return ERR_PTR(-ENOENT); return d_obtain_alias(inode); }
int yramfs_dir_link(struct dentry *old_dentry, struct inode *dir, struct dentry * dentry) { DBG_PRINT("linking for %s", dentry->d_name.name); struct inode *inode = old_dentry->d_inode; inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; inc_nlink(inode); ihold(inode); dget(dentry); d_instantiate(dentry, inode); return 0; }
static int minix_link(struct dentry * old_dentry, struct inode * dir, struct dentry *dentry) { struct inode *inode = old_dentry->d_inode; if (inode->i_nlink >= minix_sb(inode->i_sb)->s_link_max) return -EMLINK; inode->i_ctime = CURRENT_TIME_SEC; inode_inc_link_count(inode); ihold(inode); return add_nondir(dentry, inode); }
/* * convert regular fh to dentry * * FIXME: we should try harder by querying the mds for the ino. */ static struct dentry *__fh_to_dentry(struct super_block *sb, struct ceph_nfs_fh *fh, int fh_len) { struct ceph_mds_client *mdsc = ceph_sb_to_client(sb)->mdsc; struct inode *inode; struct dentry *dentry; struct ceph_vino vino; int err; if (fh_len < sizeof(*fh) / 4) return ERR_PTR(-ESTALE); dout("__fh_to_dentry %llx\n", fh->ino); vino.ino = fh->ino; vino.snap = CEPH_NOSNAP; inode = ceph_find_inode(sb, vino); if (!inode) { struct ceph_mds_request *req; req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_LOOKUPINO, USE_ANY_MDS); if (IS_ERR(req)) return ERR_CAST(req); req->r_ino1 = vino; req->r_num_caps = 1; err = ceph_mdsc_do_request(mdsc, NULL, req); inode = req->r_target_inode; if (inode) ihold(inode); ceph_mdsc_put_request(req); if (!inode) return ERR_PTR(-ESTALE); } dentry = d_obtain_alias(inode); if (IS_ERR(dentry)) { pr_err("fh_to_dentry %llx -- inode %p but ENOMEM\n", fh->ino, inode); iput(inode); return dentry; } err = ceph_init_dentry(dentry); if (err < 0) { iput(inode); return ERR_PTR(err); } dout("__fh_to_dentry %llx %p dentry %p\n", fh->ino, inode, dentry); return dentry; }
static int pmfs_link(struct dentry *dest_dentry, struct inode *dir, struct dentry *dentry) { struct super_block *sb = dir->i_sb; struct inode *inode = dest_dentry->d_inode; struct pmfs_inode *pi = pmfs_get_inode(sb, inode); struct pmfs_inode *pidir; u64 pidir_tail = 0, pi_tail = 0; int err = -ENOMEM; timing_t link_time; PMFS_START_TIMING(link_t, link_time); if (inode->i_nlink >= PMFS_LINK_MAX) { err = -EMLINK; goto out; } pidir = pmfs_get_inode(sb, dir); if (!pidir) { err = -EINVAL; goto out; } ihold(inode); pmfs_dbgv("%s: name %s, dest %s, inode %lu, dir %lu\n", __func__, dentry->d_name.name, dest_dentry->d_name.name, inode->i_ino, dir->i_ino); err = pmfs_add_entry(dentry, NULL, inode->i_ino, 0, 0, 0, &pidir_tail); if (err) { iput(inode); goto out; } inode->i_ctime = CURRENT_TIME_SEC; inc_nlink(inode); err = pmfs_append_link_change_entry(sb, pi, inode, 0, &pi_tail); if (err) { iput(inode); goto out; } d_instantiate(dentry, inode); pmfs_lite_transaction_for_time_and_link(sb, pi, pidir, pi_tail, pidir_tail, 0); out: PMFS_END_TIMING(link_t, link_time); return err; }
/* * try renew caps after session gets killed. */ int ceph_renew_caps(struct inode *inode) { struct ceph_mds_client *mdsc = ceph_sb_to_client(inode->i_sb)->mdsc; struct ceph_inode_info *ci = ceph_inode(inode); struct ceph_mds_request *req; int err, flags, wanted; spin_lock(&ci->i_ceph_lock); wanted = __ceph_caps_file_wanted(ci); if (__ceph_is_any_real_caps(ci) && (!(wanted & CEPH_CAP_ANY_WR) == 0 || ci->i_auth_cap)) { int issued = __ceph_caps_issued(ci, NULL); spin_unlock(&ci->i_ceph_lock); dout("renew caps %p want %s issued %s updating mds_wanted\n", inode, ceph_cap_string(wanted), ceph_cap_string(issued)); ceph_check_caps(ci, 0, NULL); return 0; } spin_unlock(&ci->i_ceph_lock); flags = 0; if ((wanted & CEPH_CAP_FILE_RD) && (wanted & CEPH_CAP_FILE_WR)) flags = O_RDWR; else if (wanted & CEPH_CAP_FILE_RD) flags = O_RDONLY; else if (wanted & CEPH_CAP_FILE_WR) flags = O_WRONLY; #ifdef O_LAZY if (wanted & CEPH_CAP_FILE_LAZYIO) flags |= O_LAZY; #endif req = prepare_open_request(inode->i_sb, flags, 0); if (IS_ERR(req)) { err = PTR_ERR(req); goto out; } req->r_inode = inode; ihold(inode); req->r_num_caps = 1; req->r_fmode = -1; err = ceph_mdsc_do_request(mdsc, NULL, req); ceph_mdsc_put_request(req); out: dout("renew caps %p open result=%d\n", inode, err); return err < 0 ? err : 0; }
static int v9fs_vfs_link_dotl(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) { int err; char *name; struct dentry *dir_dentry; struct p9_fid *dfid, *oldfid; struct v9fs_session_info *v9ses; P9_DPRINTK(P9_DEBUG_VFS, "dir ino: %lu, old_name: %s, new_name: %s\n", dir->i_ino, old_dentry->d_name.name, dentry->d_name.name); v9ses = v9fs_inode2v9ses(dir); dir_dentry = v9fs_dentry_from_dir_inode(dir); dfid = v9fs_fid_lookup(dir_dentry); if (IS_ERR(dfid)) return PTR_ERR(dfid); oldfid = v9fs_fid_lookup(old_dentry); if (IS_ERR(oldfid)) return PTR_ERR(oldfid); name = (char *) dentry->d_name.name; err = p9_client_link(dfid, oldfid, (char *)dentry->d_name.name); if (err < 0) { P9_DPRINTK(P9_DEBUG_VFS, "p9_client_link failed %d\n", err); return err; } v9fs_invalidate_inode_attr(dir); if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) { /* Get the latest stat info from server. */ struct p9_fid *fid; fid = v9fs_fid_lookup(old_dentry); if (IS_ERR(fid)) return PTR_ERR(fid); v9fs_refresh_inode_dotl(fid, old_dentry->d_inode); } ihold(old_dentry->d_inode); d_instantiate(dentry, old_dentry->d_inode); return err; }
static int ufs_link (struct dentry * old_dentry, struct inode * dir, struct dentry *dentry) { struct inode *inode = old_dentry->d_inode; int error; lock_ufs(dir->i_sb); inode->i_ctime = CURRENT_TIME_SEC; inode_inc_link_count(inode); ihold(inode); error = ufs_add_nondir(dentry, inode); unlock_ufs(dir->i_sb); return error; }
struct file *anon_inode_getfile(const char *name, const struct file_operations *fops, void *priv, int flags) { struct qstr this; struct path path; struct file *file; int error; if (IS_ERR(anon_inode_inode)) return ERR_PTR(-ENODEV); if (fops->owner && !try_module_get(fops->owner)) return ERR_PTR(-ENOENT); error = -ENOMEM; this.name = name; this.len = strlen(name); this.hash = 0; path.dentry = d_alloc_pseudo(anon_inode_mnt->mnt_sb, &this); if (!path.dentry) goto err_module; path.mnt = mntget(anon_inode_mnt); ihold(anon_inode_inode); d_instantiate(path.dentry, anon_inode_inode); error = -ENFILE; file = alloc_file(&path, OPEN_FMODE(flags), fops); if (!file) goto err_dput; file->f_mapping = anon_inode_inode->i_mapping; file->f_pos = 0; file->f_flags = flags & (O_ACCMODE | O_NONBLOCK); file->f_version = 0; file->private_data = priv; return file; err_dput: path_put(&path); err_module: module_put(fops->owner); return ERR_PTR(error); }
static int ufs_link (struct dentry * old_dentry, struct inode * dir, struct dentry *dentry) { struct inode *inode = d_inode(old_dentry); int error; inode->i_ctime = CURRENT_TIME_SEC; inode_inc_link_count(inode); ihold(inode); error = ufs_add_link(dentry, inode); if (error) { inode_dec_link_count(inode); iput(inode); } else d_instantiate(dentry, inode); return error; }