#define DEBUG_SUBSYSTEM S_LLITE
#include <obd_support.h>
+#include <lustre_fid.h>
#include <lustre_lite.h>
#include <lustre_dlm.h>
-#include <linux/lustre_version.h>
+#include <lustre_ver.h>
+#include <lustre_mdc.h>
#include "llite_internal.h"
/* methods */
+extern struct dentry_operations ll_d_ops;
-/* called from iget{4,5_locked}->find_inode() under inode_lock spinlock */
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
-static int ll_test_inode(struct inode *inode, unsigned long ino, void *opaque)
-#else
-static int ll_test_inode(struct inode *inode, void *opaque)
-#endif
+/*
+ * Check if we have something mounted at the named dchild.
+ * In such a case there would always be dentry present.
+ */
+static int ll_d_mountpoint(struct dentry *dparent, struct dentry *dchild,
+ struct qstr *name)
{
- static int last_ino, last_gen, last_count;
- struct lustre_md *md = opaque;
-
- if (!(md->body->valid & (OBD_MD_FLGENER | OBD_MD_FLID))) {
- CERROR("MDS body missing inum or generation\n");
- return 0;
- }
-
- if (last_ino == md->body->ino && last_gen == md->body->generation &&
- last_count < 500) {
- last_count++;
- } else {
- if (last_count > 1)
- CDEBUG(D_VFSTRACE, "compared %u/%u %u times\n",
- last_ino, last_gen, last_count);
- last_count = 0;
- last_ino = md->body->ino;
- last_gen = md->body->generation;
- CDEBUG(D_VFSTRACE,
- "comparing inode %p ino %lu/%u to body "LPU64"/%u\n",
- inode, inode->i_ino, inode->i_generation,
- md->body->ino, md->body->generation);
- }
-
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
- if (inode->i_ino != md->body->ino)
- return 0;
-#endif
- if (inode->i_generation != md->body->generation) {
-#ifdef HAVE_EXPORT___IGET
- if (inode->i_state & (I_FREEING | I_CLEAR))
- return 0;
- if (inode->i_nlink == 0)
- return 0;
-
- /* add "duplicate" inode into deathrow for destroy */
- spin_lock(&ll_i2sbi(inode)->ll_deathrow_lock);
- if (list_empty(&ll_i2info(inode)->lli_dead_list)) {
- __iget(inode);
- list_add(&ll_i2info(inode)->lli_dead_list,
- &ll_i2sbi(inode)->ll_deathrow);
+ int mounted = 0;
+
+ if (unlikely(dchild)) {
+ mounted = d_mountpoint(dchild);
+ } else if (dparent) {
+ dchild = d_lookup(dparent, name);
+ if (dchild) {
+ mounted = d_mountpoint(dchild);
+ dput(dchild);
}
- spin_unlock(&ll_i2sbi(inode)->ll_deathrow_lock);
-#endif
-
- return 0;
}
-
- /* Apply the attributes in 'opaque' to this inode */
- if (!(inode->i_state & (I_FREEING | I_CLEAR)))
- ll_update_inode(inode, md);
- return 1;
+ return mounted;
}
-extern struct dentry_operations ll_d_ops;
-
int ll_unlock(__u32 mode, struct lustre_handle *lockh)
{
ENTRY;
RETURN(0);
}
-/* Get an inode by inode number (already instantiated by the intent lookup).
+/*
+ * Get an inode by inode number (already instantiated by the intent lookup).
* Returns inode or NULL
*/
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0))
-int ll_set_inode(struct inode *inode, void *opaque)
-{
- ll_read_inode2(inode, opaque);
- return 0;
-}
-
struct inode *ll_iget(struct super_block *sb, ino_t hash,
struct lustre_md *md)
{
+ struct ll_inode_info *lli;
struct inode *inode;
-
LASSERT(hash != 0);
- inode = iget5_locked(sb, hash, ll_test_inode, ll_set_inode, md);
+ inode = iget_locked(sb, hash);
if (inode) {
- if (inode->i_state & I_NEW)
+ if (inode->i_state & I_NEW) {
+ lli = ll_i2info(inode);
+ ll_read_inode2(inode, md);
unlock_new_inode(inode);
- CDEBUG(D_VFSTRACE, "inode: %lu/%u(%p)\n", inode->i_ino,
- inode->i_generation, inode);
+ } else {
+ if (!(inode->i_state & (I_FREEING | I_CLEAR)))
+ ll_update_inode(inode, md);
+ }
+ CDEBUG(D_VFSTRACE, "inode: %lu/%u(%p)\n",
+ inode->i_ino, inode->i_generation, inode);
}
return inode;
{
struct inode *inode;
LASSERT(hash != 0);
- inode = iget4(sb, hash, ll_test_inode, md);
- if (inode)
- CDEBUG(D_VFSTRACE, "inode: %lu/%u(%p)\n", inode->i_ino,
- inode->i_generation, inode);
+
+ inode = iget4(sb, hash, NULL, md);
+ if (inode) {
+ if (!(inode->i_state & (I_FREEING | I_CLEAR)))
+ ll_update_inode(inode, md);
+
+ CDEBUG(D_VFSTRACE, "inode: %lu/%u(%p)\n",
+ inode->i_ino, inode->i_generation, inode);
+ }
return inode;
}
#endif
-int ll_mdc_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc,
- void *data, int flag)
+static void ll_drop_negative_dentry(struct inode *dir)
+{
+ struct dentry *dentry, *tmp_alias, *tmp_subdir;
+
+ spin_lock(&dcache_lock);
+restart:
+ list_for_each_entry_safe(dentry, tmp_alias,
+ &dir->i_dentry,d_alias) {
+ if (!list_empty(&dentry->d_subdirs)) {
+ struct dentry *child;
+ list_for_each_entry_safe(child, tmp_subdir,
+ &dentry->d_subdirs,
+ d_child) {
+ /* XXX Print some debug here? */
+ if (!child->d_inode)
+ /* Negative dentry. If we were
+ dropping dcache lock, go
+ throught the list again */
+ if (ll_drop_dentry(child))
+ goto restart;
+ }
+ }
+ }
+ spin_unlock(&dcache_lock);
+}
+
+
+int ll_md_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc,
+ void *data, int flag)
{
int rc;
struct lustre_handle lockh;
case LDLM_CB_CANCELING: {
struct inode *inode = ll_inode_from_lock(lock);
__u64 bits = lock->l_policy_data.l_inodebits.bits;
+ struct lu_fid *fid;
/* Invalidate all dentries associated with this inode */
if (inode == NULL)
break;
- if (lock->l_resource->lr_name.name[0] != inode->i_ino ||
- lock->l_resource->lr_name.name[1] != inode->i_generation) {
- LDLM_ERROR(lock, "data mismatch with ino %lu/%u (%p)",
- inode->i_ino, inode->i_generation, inode);
+ fid = ll_inode2fid(inode);
+ if (lock->l_resource->lr_name.name[0] != fid_seq(fid) ||
+ lock->l_resource->lr_name.name[1] != fid_oid(fid) ||
+ lock->l_resource->lr_name.name[2] != fid_ver(fid)) {
+ LDLM_ERROR(lock, "data mismatch with object "
+ DFID" (%p)", PFID(fid), inode);
}
if (bits & MDS_INODELOCK_OPEN) {
break;
case LCK_PR:
flags = FMODE_EXEC;
- if (!FMODE_EXEC)
- CERROR("open PR lock without FMODE_EXEC\n");
break;
case LCK_CR:
flags = FMODE_READ;
"%d, inode %ld\n", lock->l_req_mode,
inode->i_ino);
}
- ll_mdc_real_close(inode, flags);
+ ll_md_real_close(inode, flags);
}
if (bits & MDS_INODELOCK_UPDATE)
- clear_bit(LLI_F_HAVE_MDS_SIZE_LOCK,
- &(ll_i2info(inode)->lli_flags));
+ ll_i2info(inode)->lli_flags &= ~LLIF_MDS_SIZE_LOCK;
if (S_ISDIR(inode->i_mode) &&
(bits & MDS_INODELOCK_UPDATE)) {
- struct dentry *dentry, *tmp, *dir;
- int alias_counter = 0;
-
CDEBUG(D_INODE, "invalidating inode %lu\n",
inode->i_ino);
truncate_inode_pages(inode->i_mapping, 0);
-
- /* Drop possible cached negative dentries */
- dir = NULL;
- spin_lock(&dcache_lock);
-
- /* It is possible to have several dentries (with
- racer?) */
- list_for_each_entry_safe(dentry, tmp,
- &inode->i_dentry,d_alias) {
- if (!list_empty(&dentry->d_subdirs))
- dir = dentry;
- alias_counter ++;
- }
-
- if (alias_counter > 1)
- CWARN("More than 1 alias dir %lu alias %d\n",
- inode->i_ino, alias_counter);
-
- if (dir) {
-restart:
- list_for_each_entry_safe(dentry, tmp,
- &dir->d_subdirs,
- d_child)
- {
- /* XXX Print some debug here? */
- if (!dentry->d_inode)
- /* Negative dentry. If we were
- dropping dcache lock, go
- throught the list again */
- if (ll_drop_dentry(dentry))
- goto restart;
- }
- }
- spin_unlock(&dcache_lock);
+ ll_drop_negative_dentry(inode);
}
if (inode->i_sb->s_root &&
RETURN(0);
}
-int ll_mdc_cancel_unused(struct lustre_handle *conn, struct inode *inode,
- int flags, void *opaque)
-{
- struct ldlm_res_id res_id =
- { .name = {inode->i_ino, inode->i_generation} };
- struct obd_device *obddev = class_conn2obd(conn);
- ENTRY;
-
- RETURN(ldlm_cli_cancel_unused(obddev->obd_namespace, &res_id, flags,
- opaque));
-}
-
/* Pack the required supplementary groups into the supplied groups array.
* If we don't need to use the groups from the target inode(s) then we
* instead pack one or more groups from the user's supplementary group
}
}
-int ll_prepare_mdc_op_data(struct mdc_op_data *data, struct inode *i1,
- struct inode *i2, const char *name, int namelen,
- int mode)
-{
- LASSERT(i1);
-
- if (namelen > ll_i2sbi(i1)->ll_namelen)
- return -ENAMETOOLONG;
- ll_i2gids(data->suppgids, i1, i2);
- ll_inode2fid(&data->fid1, i1);
-
- if (i2)
- ll_inode2fid(&data->fid2, i2);
- else
- memset(&data->fid2, 0, sizeof(data->fid2));
-
- data->name = name;
- data->namelen = namelen;
- data->create_mode = mode;
- data->mod_time = CURRENT_SECONDS;
-
- return 0;
-}
-
static void ll_d_add(struct dentry *de, struct inode *inode)
{
CDEBUG(D_DENTRY, "adding inode %p to dentry %p\n", inode, de);
struct list_head *tmp;
struct dentry *dentry;
struct dentry *last_discon = NULL;
-
+
spin_lock(&dcache_lock);
list_for_each(tmp, &inode->i_dentry) {
dentry = list_entry(tmp, struct dentry, d_alias);
de->d_parent, de->d_inode, atomic_read(&de->d_count));
return dentry;
}
+
if (last_discon) {
- CDEBUG(D_DENTRY, "Reuse disconnected dentry %p inode %p "
+ CDEBUG(D_DENTRY, "Reuse disconnected dentry %p inode %p "
"refc %d\n", last_discon, last_discon->d_inode,
atomic_read(&last_discon->d_count));
- dget_locked(last_discon);
- spin_unlock(&dcache_lock);
- d_rehash(de);
- d_move(last_discon, de);
- iput(inode);
- return last_discon;
+ __d_rehash(de, 0);
+ dget_locked(last_discon);
+ __d_move(last_discon, de);
+ spin_unlock(&dcache_lock);
+ d_rehash(de);
+ iput(inode);
+ return last_discon;
}
-
+
ll_d_add(de, inode);
spin_unlock(&dcache_lock);
if (!it_disposition(it, DISP_LOOKUP_NEG)) {
ENTRY;
- rc = ll_prep_inode(sbi->ll_osc_exp, &inode, request, offset,
+ rc = ll_prep_inode(&inode, request, offset,
(*de)->d_sb);
if (rc)
RETURN(rc);
CDEBUG(D_DLMTRACE, "setting l_data to inode %p (%lu/%u)\n",
inode, inode->i_ino, inode->i_generation);
- mdc_set_lock_data(&it->d.lustre.it_lock_handle, inode);
+ md_set_lock_data(sbi->ll_md_exp,
+ &it->d.lustre.it_lock_handle, inode);
/* We used to query real size from OSTs here, but actually
this is not needed. For stat() calls size would be updated
Everybody else who needs correct file size would call
ll_glimpse_size or some equivalent themselves anyway.
Also see bug 7198. */
+
*de = ll_find_alias(inode, *de);
} else {
ENTRY;
ll_d_add(*de, inode);
spin_unlock(&dcache_lock);
} else {
+ (*de)->d_inode = NULL;
/* We do not want to hash the dentry if don`t have a
* lock, but if this dentry is later used in d_move,
* we'd hit uninitialised list head d_hash, so we just
static struct dentry *ll_lookup_it(struct inode *parent, struct dentry *dentry,
struct lookup_intent *it, int lookup_flags)
{
+ struct lookup_intent lookup_it = { .it_op = IT_LOOKUP };
struct dentry *save = dentry, *retval;
- struct mdc_op_data op_data;
- struct it_cb_data icbd;
struct ptlrpc_request *req = NULL;
- struct lookup_intent lookup_it = { .it_op = IT_LOOKUP };
+ struct md_op_data *op_data;
+ struct it_cb_data icbd;
+ __u32 opc;
int rc;
ENTRY;
+ if (dentry->d_name.len > ll_i2sbi(parent)->ll_namelen)
+ RETURN(ERR_PTR(-ENAMETOOLONG));
+
CDEBUG(D_VFSTRACE, "VFS Op:name=%.*s,dir=%lu/%u(%p),intent=%s\n",
dentry->d_name.len, dentry->d_name.name, parent->i_ino,
parent->i_generation, parent, LL_IT2STR(it));
icbd.icbd_childp = &dentry;
icbd.icbd_parent = parent;
- rc = ll_prepare_mdc_op_data(&op_data, parent, NULL, dentry->d_name.name,
- dentry->d_name.len, lookup_flags);
- if (rc)
- RETURN(ERR_PTR(rc));
+ if (it->it_op & IT_CREAT ||
+ (it->it_op & IT_OPEN && it->it_create_mode & O_CREAT))
+ opc = LUSTRE_OPC_CREATE;
+ else
+ opc = LUSTRE_OPC_ANY;
- it->it_create_mode &= ~current->fs->umask;
+ op_data = ll_prep_md_op_data(NULL, parent, NULL, dentry->d_name.name,
+ dentry->d_name.len, lookup_flags, opc);
+ if (IS_ERR(op_data))
+ RETURN((void *)op_data);
- rc = mdc_intent_lock(ll_i2mdcexp(parent), &op_data, NULL, 0, it,
- lookup_flags, &req, ll_mdc_blocking_ast, 0);
+ it->it_create_mode &= ~current->fs->umask;
+ rc = md_intent_lock(ll_i2mdexp(parent), op_data, NULL, 0, it,
+ lookup_flags, &req, ll_md_blocking_ast, 0);
+ ll_finish_md_op_data(op_data);
if (rc < 0)
GOTO(out, retval = ERR_PTR(rc));
LASSERT(it_disposition(it, DISP_ENQ_CREATE_REF));
request = it->d.lustre.it_data;
it_clear_disposition(it, DISP_ENQ_CREATE_REF);
- rc = ll_prep_inode(sbi->ll_osc_exp, &inode, request, DLM_REPLY_REC_OFF,
- dir->i_sb);
+ rc = ll_prep_inode(&inode, request, DLM_REPLY_REC_OFF, dir->i_sb);
if (rc)
GOTO(out, inode = ERR_PTR(rc));
* stuff it in the lock. */
CDEBUG(D_DLMTRACE, "setting l_ast_data to inode %p (%lu/%u)\n",
inode, inode->i_ino, inode->i_generation);
- mdc_set_lock_data(&it->d.lustre.it_lock_handle, inode);
+ md_set_lock_data(sbi->ll_md_exp,
+ &it->d.lustre.it_lock_handle, inode);
EXIT;
out:
ptlrpc_req_finished(request);
struct lookup_intent *it)
{
struct inode *inode;
- struct ptlrpc_request *request = it->d.lustre.it_data;
int rc = 0;
ENTRY;
if (rc)
RETURN(rc);
- mdc_store_inode_generation(request, DLM_INTENT_REC_OFF,
- DLM_REPLY_REC_OFF);
inode = ll_create_node(dir, dentry->d_name.name, dentry->d_name.len,
NULL, 0, mode, 0, it);
if (IS_ERR(inode)) {
static void ll_update_times(struct ptlrpc_request *request, int offset,
struct inode *inode)
{
- struct mds_body *body = lustre_msg_buf(request->rq_repmsg, offset,
+ struct mdt_body *body = lustre_msg_buf(request->rq_repmsg, offset,
sizeof(*body));
LASSERT(body);
}
static int ll_new_node(struct inode *dir, struct qstr *name,
- const char *tgt, int mode,
- int rdev, struct dentry *dchild)
+ const char *tgt, int mode, int rdev,
+ struct dentry *dchild, __u32 opc)
{
struct ptlrpc_request *request = NULL;
+ struct md_op_data *op_data;
struct inode *inode = NULL;
struct ll_sb_info *sbi = ll_i2sbi(dir);
- struct mdc_op_data op_data;
int tgt_len = 0;
int err;
ENTRY;
if (unlikely(tgt != NULL))
- tgt_len = strlen(tgt)+1;
+ tgt_len = strlen(tgt) + 1;
- err = ll_prepare_mdc_op_data(&op_data, dir, NULL, name->name,
- name->len, 0);
- if (err)
- GOTO(err_exit, err);
+ op_data = ll_prep_md_op_data(NULL, dir, NULL, name->name,
+ name->len, 0, opc);
+ if (IS_ERR(op_data))
+ GOTO(err_exit, err = PTR_ERR(op_data));
- err = mdc_create(sbi->ll_mdc_exp, &op_data, tgt, tgt_len,
- mode, current->fsuid, current->fsgid,
- current->cap_effective, rdev, &request);
+ err = md_create(sbi->ll_md_exp, op_data, tgt, tgt_len, mode,
+ current->fsuid, current->fsgid,
+ current->cap_effective, rdev, &request);
+ ll_finish_md_op_data(op_data);
if (err)
GOTO(err_exit, err);
ll_update_times(request, REPLY_REC_OFF, dir);
if (dchild) {
- err = ll_prep_inode(sbi->ll_osc_exp, &inode, request,
- REPLY_REC_OFF, dchild->d_sb);
+ err = ll_prep_inode(&inode, request, REPLY_REC_OFF,
+ dchild->d_sb);
if (err)
GOTO(err_exit, err);
return err;
}
-
static int ll_mknod_generic(struct inode *dir, struct qstr *name, int mode,
unsigned rdev, struct dentry *dchild)
{
case S_IFBLK:
case S_IFIFO:
case S_IFSOCK:
- err = ll_new_node(dir, name, NULL, mode, rdev, dchild);
+ err = ll_new_node(dir, name, NULL, mode, rdev, dchild,
+ LUSTRE_OPC_MKNOD);
break;
case S_IFDIR:
err = -EPERM;
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
#ifndef LUSTRE_KERNEL_VERSION
-static int ll_create_nd(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd)
+static int ll_create_nd(struct inode *dir, struct dentry *dentry,
+ int mode, struct nameidata *nd)
{
struct lookup_intent *it = ll_d2d(dentry)->lld_it;
int rc;
return rc;
}
#else
-static int ll_create_nd(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd)
+static int ll_create_nd(struct inode *dir, struct dentry *dentry,
+ int mode, struct nameidata *nd)
{
-
if (!nd || !nd->intent.d.lustre.it_disposition)
/* No saved request? Just mknod the file */
return ll_mknod_generic(dir, &dentry->d_name, mode, 0, dentry);
dir, 3000, tgt);
err = ll_new_node(dir, name, (char *)tgt, S_IFLNK | S_IRWXUGO,
- 0, dchild);
+ 0, dchild, LUSTRE_OPC_SYMLINK);
RETURN(err);
}
static int ll_link_generic(struct inode *src, struct inode *dir,
struct qstr *name, struct dentry *dchild)
{
+ struct ll_sb_info *sbi = ll_i2sbi(dir);
struct ptlrpc_request *request = NULL;
- struct mdc_op_data op_data;
+ struct md_op_data *op_data;
int err;
- struct ll_sb_info *sbi = ll_i2sbi(dir);
ENTRY;
CDEBUG(D_VFSTRACE,
src->i_ino, src->i_generation, src, dir->i_ino,
dir->i_generation, dir, name->len, name->name);
- err = ll_prepare_mdc_op_data(&op_data, src, dir, name->name,
- name->len, 0);
+ op_data = ll_prep_md_op_data(NULL, src, dir, name->name, name->len,
+ 0, LUSTRE_OPC_ANY);
+ if (IS_ERR(op_data))
+ RETURN(PTR_ERR(op_data));
+
+ err = md_link(sbi->ll_md_exp, op_data, &request);
+ ll_finish_md_op_data(op_data);
if (err)
GOTO(out, err);
- err = mdc_link(sbi->ll_mdc_exp, &op_data, &request);
- if (err)
- GOTO(out, err);
-
- if (dchild) {
+ if (dchild)
d_drop(dchild);
- }
- ll_update_times(request, REPLY_REC_OFF, dir);
+ ll_update_times(request, REPLY_REC_OFF, dir);
EXIT;
out:
ptlrpc_req_finished(request);
RETURN(err);
}
-static int ll_mkdir_generic(struct inode *dir, struct qstr *name, int mode,
- struct dentry *dchild)
+static int ll_mkdir_generic(struct inode *dir, struct qstr *name,
+ int mode, struct dentry *dchild)
{
int err;
-
ENTRY;
+
CDEBUG(D_VFSTRACE, "VFS Op:name=%.*s,dir=%lu/%u(%p)\n",
name->len, name->name, dir->i_ino, dir->i_generation, dir);
mode = (mode & (S_IRWXUGO|S_ISVTX) & ~current->fs->umask) | S_IFDIR;
- err = ll_new_node(dir, name, NULL, mode, 0, dchild);
+ err = ll_new_node(dir, name, NULL, mode, 0, dchild, LUSTRE_OPC_MKDIR);
RETURN(err);
}
static int ll_rmdir_generic(struct inode *dir, struct dentry *dparent,
- struct qstr *name)
+ struct dentry *dchild, struct qstr *name)
{
struct ptlrpc_request *request = NULL;
- struct mdc_op_data op_data;
- struct dentry *dentry;
+ struct md_op_data *op_data;
int rc;
ENTRY;
+
CDEBUG(D_VFSTRACE, "VFS Op:name=%.*s,dir=%lu/%u(%p)\n",
name->len, name->name, dir->i_ino, dir->i_generation, dir);
- /* Check if we have something mounted at the dir we are going to delete
- * In such a case there would always be dentry present. */
- if (dparent) {
- dentry = d_lookup(dparent, name);
- if (dentry) {
- int mounted = d_mountpoint(dentry);
- dput(dentry);
- if (mounted)
- GOTO(out, rc = -EBUSY);
- }
- }
+ if (unlikely(ll_d_mountpoint(dparent, dchild, name)))
+ RETURN(-EBUSY);
- rc = ll_prepare_mdc_op_data(&op_data, dir, NULL, name->name,
- name->len, S_IFDIR);
- if (rc)
- GOTO(out, rc);
- rc = mdc_unlink(ll_i2sbi(dir)->ll_mdc_exp, &op_data, &request);
- if (rc)
- GOTO(out, rc);
- ll_update_times(request, REPLY_REC_OFF, dir);
+ op_data = ll_prep_md_op_data(NULL, dir, NULL, name->name, name->len,
+ S_IFDIR, LUSTRE_OPC_ANY);
+ if (IS_ERR(op_data))
+ RETURN(PTR_ERR(op_data));
- EXIT;
-out:
+ rc = md_unlink(ll_i2sbi(dir)->ll_md_exp, op_data, &request);
+ ll_finish_md_op_data(op_data);
+ if (rc == 0)
+ ll_update_times(request, REPLY_REC_OFF, dir);
ptlrpc_req_finished(request);
- return(rc);
+ RETURN(rc);
}
int ll_objects_destroy(struct ptlrpc_request *request, struct inode *dir)
{
- struct mds_body *body;
+ struct mdt_body *body;
struct lov_mds_md *eadata;
struct lov_stripe_md *lsm = NULL;
struct obd_trans_info oti = { 0 };
GOTO(out, rc = -EPROTO);
}
- rc = obd_unpackmd(ll_i2obdexp(dir), &lsm, eadata, body->eadatasize);
+ rc = obd_unpackmd(ll_i2dtexp(dir), &lsm, eadata, body->eadatasize);
if (rc < 0) {
CERROR("obd_unpackmd: %d\n", rc);
GOTO(out, rc);
}
LASSERT(rc >= sizeof(*lsm));
- rc = obd_checkmd(ll_i2obdexp(dir), ll_i2mdcexp(dir), lsm);
+ rc = obd_checkmd(ll_i2dtexp(dir), ll_i2mdexp(dir), lsm);
if (rc)
GOTO(out_free_memmd, rc);
- oa = obdo_alloc();
+ OBDO_ALLOC(oa);
if (oa == NULL)
GOTO(out_free_memmd, rc = -ENOMEM);
oa->o_id = lsm->lsm_object_id;
+ oa->o_gr = lsm->lsm_object_gr;
oa->o_mode = body->mode & S_IFMT;
- oa->o_valid = OBD_MD_FLID | OBD_MD_FLTYPE;
+ oa->o_valid = OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLGROUP;
if (body->valid & OBD_MD_FLCOOKIE) {
oa->o_valid |= OBD_MD_FLCOOKIE;
}
}
- rc = obd_destroy(ll_i2obdexp(dir), oa, lsm, &oti, ll_i2mdcexp(dir));
- obdo_free(oa);
+ rc = obd_destroy(ll_i2dtexp(dir), oa, lsm, &oti, ll_i2mdexp(dir));
+ OBDO_FREE(oa);
if (rc)
CERROR("obd destroy objid "LPX64" error %d\n",
lsm->lsm_object_id, rc);
out_free_memmd:
- obd_free_memmd(ll_i2obdexp(dir), &lsm);
+ obd_free_memmd(ll_i2dtexp(dir), &lsm);
out:
return rc;
}
-static int ll_unlink_generic(struct inode * dir, struct qstr *name)
+static int ll_unlink_generic(struct inode *dir, struct dentry *dparent,
+ struct dentry *dchild, struct qstr *name)
{
struct ptlrpc_request *request = NULL;
- struct mdc_op_data op_data;
+ struct md_op_data *op_data;
int rc;
ENTRY;
-
CDEBUG(D_VFSTRACE, "VFS Op:name=%.*s,dir=%lu/%u(%p)\n",
name->len, name->name, dir->i_ino, dir->i_generation, dir);
- rc = ll_prepare_mdc_op_data(&op_data, dir, NULL, name->name,
- name->len, 0);
- if (rc)
- GOTO(out, rc);
- rc = mdc_unlink(ll_i2sbi(dir)->ll_mdc_exp, &op_data, &request);
+ /*
+ * XXX: unlink bind mountpoint maybe call to here,
+ * just check it as vfs_unlink does.
+ */
+ if (unlikely(ll_d_mountpoint(dparent, dchild, name)))
+ RETURN(-EBUSY);
+
+ op_data = ll_prep_md_op_data(NULL, dir, NULL, name->name,
+ name->len, 0, LUSTRE_OPC_ANY);
+ if (IS_ERR(op_data))
+ RETURN(PTR_ERR(op_data));
+
+ rc = md_unlink(ll_i2sbi(dir)->ll_md_exp, op_data, &request);
+ ll_finish_md_op_data(op_data);
+
if (rc)
GOTO(out, rc);
ll_update_times(request, REPLY_REC_OFF, dir);
rc = ll_objects_destroy(request, dir);
- if (rc)
- GOTO(out, rc);
- EXIT;
out:
ptlrpc_req_finished(request);
- return(rc);
+ RETURN(rc);
}
-static int ll_rename_generic(struct inode *src, struct qstr *src_name,
- struct inode *tgt, struct qstr *tgt_name)
+static int ll_rename_generic(struct inode *src, struct dentry *src_dparent,
+ struct dentry *src_dchild, struct qstr *src_name,
+ struct inode *tgt, struct dentry *tgt_dparent,
+ struct dentry *tgt_dchild, struct qstr *tgt_name)
{
struct ptlrpc_request *request = NULL;
struct ll_sb_info *sbi = ll_i2sbi(src);
- struct mdc_op_data op_data;
+ struct md_op_data *op_data;
int err;
-
ENTRY;
CDEBUG(D_VFSTRACE,"VFS Op:oldname=%.*s,src_dir=%lu/%u(%p),newname=%.*s,"
"tgt_dir=%lu/%u(%p)\n", src_name->len, src_name->name,
src->i_ino, src->i_generation, src, tgt_name->len,
tgt_name->name, tgt->i_ino, tgt->i_generation, tgt);
- err = ll_prepare_mdc_op_data(&op_data, src, tgt, NULL, 0, 0);
- if (err)
- GOTO(out, err);
- err = mdc_rename(sbi->ll_mdc_exp, &op_data,
- src_name->name, src_name->len,
- tgt_name->name, tgt_name->len, &request);
- if (err)
- GOTO(out, err);
- ll_update_times(request, REPLY_REC_OFF, src);
- ll_update_times(request, REPLY_REC_OFF, tgt);
- err = ll_objects_destroy(request, src);
- if (err)
- GOTO(out, err);
+ if (unlikely(ll_d_mountpoint(src_dparent, src_dchild, src_name) ||
+ ll_d_mountpoint(tgt_dparent, tgt_dchild, tgt_name)))
+ RETURN(-EBUSY);
+
+ op_data = ll_prep_md_op_data(NULL, src, tgt, NULL, 0, 0,
+ LUSTRE_OPC_ANY);
+ if (IS_ERR(op_data))
+ RETURN(PTR_ERR(op_data));
+
+ err = md_rename(sbi->ll_md_exp, op_data,
+ src_name->name, src_name->len,
+ tgt_name->name, tgt_name->len, &request);
+ ll_finish_md_op_data(op_data);
+ if (!err) {
+ ll_update_times(request, REPLY_REC_OFF, src);
+ ll_update_times(request, REPLY_REC_OFF, tgt);
+ err = ll_objects_destroy(request, src);
+ }
- EXIT;
-out:
ptlrpc_req_finished(request);
- return(err);
+ RETURN(err);
}
#ifdef LUSTRE_KERNEL_VERSION
}
static int ll_rename_raw(struct nameidata *srcnd, struct nameidata *tgtnd)
{
- return ll_rename_generic(srcnd->dentry->d_inode, &srcnd->last,
- tgtnd->dentry->d_inode, &tgtnd->last);
+ return ll_rename_generic(srcnd->dentry->d_inode, srcnd->dentry,
+ NULL, &srcnd->last,
+ tgtnd->dentry->d_inode, tgtnd->dentry,
+ NULL, &tgtnd->last);
}
static int ll_link_raw(struct nameidata *srcnd, struct nameidata *tgtnd)
{
}
static int ll_rmdir_raw(struct nameidata *nd)
{
- return ll_rmdir_generic(nd->dentry->d_inode, nd->dentry, &nd->last);
+ return ll_rmdir_generic(nd->dentry->d_inode, nd->dentry, NULL,
+ &nd->last);
}
static int ll_mkdir_raw(struct nameidata *nd, int mode)
{
}
static int ll_unlink_raw(struct nameidata *nd)
{
- return ll_unlink_generic(nd->dentry->d_inode, &nd->last);
+ return ll_unlink_generic(nd->dentry->d_inode, nd->dentry, NULL,
+ &nd->last);
}
#endif
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
static int ll_unlink(struct inode * dir, struct dentry *dentry)
{
- return ll_unlink_generic(dir, &dentry->d_name);
+ return ll_unlink_generic(dir, NULL, dentry, &dentry->d_name);
}
static int ll_mkdir(struct inode *dir, struct dentry *dentry, int mode)
{
}
static int ll_rmdir(struct inode *dir, struct dentry *dentry)
{
- return ll_rmdir_generic(dir, NULL, &dentry->d_name);
+ return ll_rmdir_generic(dir, NULL, dentry, &dentry->d_name);
}
static int ll_symlink(struct inode *dir, struct dentry *dentry,
const char *oldname)
static int ll_link(struct dentry *old_dentry, struct inode *dir,
struct dentry *new_dentry)
{
- return ll_link_generic(old_dentry->d_inode, dir,
- &new_dentry->d_name, new_dentry);
+ return ll_link_generic(old_dentry->d_inode, dir, &new_dentry->d_name,
+ new_dentry);
}
static int ll_rename(struct inode *old_dir, struct dentry *old_dentry,
struct inode *new_dir, struct dentry *new_dentry)
{
- return ll_rename_generic(old_dir, &old_dentry->d_name, new_dir,
+ return ll_rename_generic(old_dir, NULL,
+ old_dentry, &old_dentry->d_name,
+ new_dir, NULL, new_dentry,
&new_dentry->d_name);
}
#endif