RETURN(rc);
}
+static int cml_readlink(const struct lu_context *ctx, struct md_object *mo,
+ void *buf, int buflen)
+{
+ int rc;
+ ENTRY;
+ rc = mo_readlink(ctx, md_object_next(mo), buf, buflen);
+ RETURN(rc);
+}
+
static int cml_xattr_list(const struct lu_context *ctx, struct md_object *mo,
void *buf, int buflen)
{
.moo_attr_get = cml_attr_get,
.moo_attr_set = cml_attr_set,
.moo_xattr_get = cml_xattr_get,
+ .moo_readlink = cml_readlink,
.moo_xattr_list = cml_xattr_list,
.moo_xattr_set = cml_xattr_set,
.moo_xattr_del = cml_xattr_del,
RETURN(-EFAULT);
}
+static int cmr_readlink(const struct lu_context *ctx, struct md_object *mo,
+ void *buf, int buflen)
+{
+ RETURN(-EFAULT);
+}
+
static int cmr_xattr_list(const struct lu_context *ctx, struct md_object *mo,
void *buf, int buflen)
{
.moo_attr_get = cmr_attr_get,
.moo_attr_set = cmr_attr_set,
.moo_xattr_get = cmr_xattr_get,
+ .moo_readlink = cmr_readlink,
.moo_xattr_set = cmr_xattr_set,
.moo_xattr_list = cmr_xattr_list,
.moo_xattr_del = cmr_xattr_del,
struct dt_object *dt, void *buf, int buf_len);
/*
* Create new object on this device.
+ * @target_name is the symbolic target.
*
* precondition: !lu_object_exists(ctxt, &dt->do_lu);
* postcondition: ergo(result == 0, lu_object_exists(ctxt, &dt->do_lu));
*/
int (*do_create)(const struct lu_context *ctxt, struct dt_object *dt,
- struct lu_attr *attr, struct thandle *th);
+ struct lu_attr *attr, const char *target_name,
+ struct thandle *th);
/*
* Announce that this object is going to be used as an index. This
* operation check that object supports indexing operations and
int (*do_readpage)(const struct lu_context *ctxt,
struct dt_object *dt, const struct lu_rdpg *rdpg);
+ int (*do_readlink)(const struct lu_context *ctxt,
+ struct dt_object *dt,
+ void *buf, int buf_len);
};
/*
extern const struct req_format RQF_MDS_GETXATTR;
extern const struct req_format RQF_MDS_SETXATTR;
extern const struct req_format RQF_MDS_GETATTR;
+extern const struct req_format RQF_MDS_READLINK;
extern const struct req_format RQF_MDS_CLOSE;
extern const struct req_format RQF_MDS_PIN;
extern const struct req_format RQF_MDS_CONNECT;
int (*moo_xattr_del)(const struct lu_context *ctxt,
struct md_object *obj, const char *name);
+ int (*moo_readlink)(const struct lu_context *ctxt,
+ struct md_object *obj,
+ void *buf, int buf_len);
+
/* part of cross-ref operation */
int (*moo_object_create)(const struct lu_context *,
struct md_object *, struct md_attr *);
return m->mo_ops->moo_attr_get(cx, m, at);
}
+static inline int mo_readlink(const struct lu_context *cx, struct md_object *m,
+ void *buf, int buf_len)
+{
+ LASSERT(m->mo_ops->moo_attr_get);
+ return m->mo_ops->moo_readlink(cx, m, buf, buf_len);
+}
+
static inline int mo_attr_set(const struct lu_context *cx, struct md_object *m,
const struct lu_attr *at)
{
RETURN(rc);
}
+static int mdd_readlink(const struct lu_context *ctxt, struct md_object *obj,
+ void *buf, int buf_len)
+{
+ struct mdd_object *mdd_obj = md2mdd_obj(obj);
+ struct dt_object *next;
+ int rc;
+ ENTRY;
+
+ LASSERT(lu_object_exists(ctxt, &obj->mo_lu));
+
+ next = mdd_object_child(mdd_obj);
+ rc = next->do_ops->do_readlink(ctxt, next, buf, buf_len);
+
+ RETURN(rc);
+}
static int mdd_xattr_list(const struct lu_context *ctxt, struct md_object *obj,
void *buf, int buf_len)
{
static int __mdd_object_create(const struct lu_context *ctxt,
struct mdd_object *obj, struct md_attr *ma,
+ const char *target_name,
struct thandle *handle)
{
struct dt_object *next;
if (!lu_object_exists(ctxt, mdd2lu_obj(obj))) {
next = mdd_object_child(obj);
- rc = next->do_ops->do_create(ctxt, next, attr, handle);
+ rc = next->do_ops->do_create(ctxt, next, attr,
+ target_name, handle);
} else
rc = -EEXIST;
if (IS_ERR(handle))
RETURN(PTR_ERR(handle));
- rc = __mdd_object_create(ctxt, md2mdd_obj(obj), attr, handle);
+ rc = __mdd_object_create(ctxt, md2mdd_obj(obj), attr, NULL, handle);
mdd_trans_stop(ctxt, mdd, handle);
* Maybe we should do the same. For now: creation-first.
*/
- rc = __mdd_object_create(ctxt, son, ma, handle);
-
+ rc = __mdd_object_create(ctxt, son, ma, target_name, handle);
if (rc)
GOTO(cleanup, rc);
.moo_attr_get = mdd_attr_get,
.moo_attr_set = mdd_attr_set,
.moo_xattr_get = mdd_xattr_get,
+ .moo_readlink = mdd_readlink,
.moo_xattr_set = mdd_xattr_set,
.moo_xattr_list = mdd_xattr_list,
.moo_xattr_del = mdd_xattr_del,
goto skip_packing;
/* pre-getattr: to guess how many bytes we need. */
- if (mdt_body_has_lov(la, reqbody)) {
- /* this should return the total length, or error */
- rc = mo_xattr_get(ctxt, next, NULL, 0, XATTR_NAME_LOV);
-
- CDEBUG(D_INODE, "got %d(max=%d) bytes MD data for "DFID3"\n",
- rc, info->mti_mdt->mdt_max_mdsize,
- PFID3(mdt_object_fid(o)));
- if (rc < 0) {
- if (rc != -ENODATA && rc != -EOPNOTSUPP) {
- RETURN(rc);
- }
- rc = 0;
- } else if (rc > info->mti_mdt->mdt_max_mdsize) {
- rc = 0;
- }
- } else if (S_ISLNK(la->la_mode) && (reqbody->valid & OBD_MD_LINKNAME)) {
- /* NB: It also uses the mdt_md to hold symname. */
+ if (S_ISLNK(la->la_mode) && (reqbody->valid & OBD_MD_LINKNAME)) {
+ /*FIXME: temporary using old style, will fix it soon */
+ int size[2] = {sizeof (struct mdt_body) };
+ CDEBUG(D_INODE, "LNK name len = %lu, space in body = %d\n",
+ (unsigned long)la->la_size + 1,
+ reqbody->eadatasize);
rc = min_t(int, la->la_size + 1, reqbody->eadatasize);
+ size[1] = rc;
+ rc = lustre_pack_reply(req, 2, size, NULL);
+ if (rc)
+ RETURN(rc);
+ goto skip_packing;
}
- req_capsule_set_size(pill, &RMF_MDT_MD, RCL_SERVER, rc);
-
#ifdef CONFIG_FS_POSIX_ACL
if ((req->rq_export->exp_connect_flags & OBD_CONNECT_ACL) &&
(reqbody->valid & OBD_MD_FLACL)) {
repbody = req_capsule_server_get(pill, &RMF_MDT_BODY);
mdt_pack_attr2body(repbody, la, mdt_object_fid(o));
- buffer = req_capsule_server_get(pill, &RMF_MDT_MD);
- length = req_capsule_get_size(pill, &RMF_MDT_MD, RCL_SERVER);
-
/* now, to getattr*/
if (mdt_body_has_lov(la, reqbody)) {
+ buffer = req_capsule_server_get(pill, &RMF_MDT_MD);
+ length = req_capsule_get_size(pill, &RMF_MDT_MD, RCL_SERVER);
if (length > 0) {
rc = mo_xattr_get(ctxt, next,
buffer, length, XATTR_NAME_LOV);
}
} else if (S_ISLNK(la->la_mode) &&
(reqbody->valid & OBD_MD_LINKNAME) != 0) {
- /* FIXME How to readlink??
- rc = mo_xattr_get(ctxt, next, buffer, length, "readlink");
- */ rc = 10;
+ /*FIXME: temporary using old style, will fix it soon */
+ buffer = lustre_msg_buf(req->rq_repmsg, 1, 0);
+ LASSERT(buffer != NULL); /* caller prepped reply */
+ length = req->rq_repmsg->buflens[1];
+
+ rc = mo_readlink(ctxt, next, buffer, length);
if (rc <= 0) {
CERROR("readlink failed: %d\n", rc);
rc = -EFAULT;
repbody->valid |= OBD_MD_LINKNAME;
repbody->eadatasize = rc + 1;
((char*)buffer)[rc] = 0; /* NULL terminate */
+ CDEBUG(D_INODE, "symlink dest %s, len = %d\n",
+ (char*)buffer, rc);
rc = 0;
- CDEBUG(D_INODE, "symlink dest %s\n", (char*)buffer);
}
+ RETURN(0);
}
if (reqbody->valid & OBD_MD_FLMODEASIZE) {
repbody->max_mdsize = info->mti_mdt->mdt_max_mdsize;
repbody->valid |= OBD_MD_FLMODEASIZE;
CDEBUG(D_INODE, "I am going to change the MAX_MD_SIZE & MAX_COOKIE"
- "to : %d:%d\n",
- repbody->max_cookiesize,
- repbody->max_mdsize);
+ " to : %d:%d\n",
+ repbody->max_mdsize,
+ repbody->max_cookiesize);
}
if (rc != 0)
if (rc != 0)
GOTO(out_unlock_target, rc);
+ if (lu_fid_eq(old_fid, rr->rr_fid1) || lu_fid_eq(old_fid, rr->rr_fid2))
+ GOTO(out_unlock_target, rc = -EINVAL);
+
lh_oldp = &info->mti_lh[MDT_LH_OLD];
lh_oldp->mlh_mode = LCK_EX;
mold = mdt_object_find_lock(info, old_fid, lh_oldp,
if (lu_fid_eq(old_fid, new_fid))
GOTO(out_unlock_old, rc);
+ if (lu_fid_eq(new_fid, rr->rr_fid1) ||
+ lu_fid_eq(new_fid, rr->rr_fid2))
+ GOTO(out_unlock_old, rc = -EINVAL);
+
lh_newp->mlh_mode = LCK_EX;
mnew = mdt_object_find_lock(info, new_fid, lh_newp,
MDS_INODELOCK_FULL);
#define osd_invariant(obj) (1)
#endif
+/* helper to push us into KERNEL_DS context */
+static struct file *osd_rw_init(const struct lu_context *ctxt,
+ struct inode *inode, mm_segment_t *seg)
+{
+ struct osd_thread_info *info = lu_context_key_get(ctxt, &osd_key);
+ struct dentry *dentry = &info->oti_dentry;
+ struct file *file = &info->oti_file;
+
+ file->f_dentry = dentry;
+ file->f_mapping = inode->i_mapping;
+ file->f_op = inode->i_fop;
+ file->f_mode = FMODE_WRITE|FMODE_READ;
+ dentry->d_inode = inode;
+
+ *seg = get_fs();
+ set_fs(KERNEL_DS);
+ return file;
+}
+
+/* helper to pop us from KERNEL_DS context */
+static void osd_rw_fini(mm_segment_t *seg)
+{
+ set_fs(*seg);
+}
+
static int osd_root_get(const struct lu_context *ctx,
struct dt_device *dev, struct lu_fid *f)
{
}
static int osd_mkfile(struct osd_thread_info *info, struct osd_object *obj,
- umode_t mode, struct thandle *th)
+ umode_t mode, const char *target_name, struct thandle *th)
{
int result;
struct osd_device *osd = osd_obj2dev(obj);
dentry = d_alloc(osd->od_obj_area, &info->oti_str);
if (dentry != NULL) {
- result = dir->i_op->create(dir, dentry, mode, NULL);
+ if (S_ISLNK(mode))
+ result = dir->i_op->symlink(dir, dentry, target_name);
+ else
+ result = dir->i_op->create(dir, dentry, mode, NULL);
if (result == 0) {
LASSERT(dentry->d_inode != NULL);
obj->oo_inode = dentry->d_inode;
};
static int osd_mkdir(struct osd_thread_info *info, struct osd_object *obj,
- struct lu_attr *attr, struct thandle *th)
+ struct lu_attr *attr, const char *target_name,
+ struct thandle *th)
{
int result;
struct osd_thandle *oth;
LASSERT(S_ISDIR(attr->la_mode));
result = osd_mkfile(info, obj,
S_IFDIR | (attr->la_mode & (S_IRWXUGO|S_ISVTX)),
- th);
+ target_name, th);
if (result == 0) {
LASSERT(obj->oo_inode != NULL);
/*
}
static int osd_mkreg(struct osd_thread_info *info, struct osd_object *obj,
- struct lu_attr *attr, struct thandle *th)
+ struct lu_attr *attr, const char *target_name,
+ struct thandle *th)
{
LASSERT(S_ISREG(attr->la_mode));
return osd_mkfile(info, obj,
- S_IFREG | (attr->la_mode & (S_IRWXUGO|S_ISVTX)), th);
+ S_IFREG | (attr->la_mode & (S_IRWXUGO|S_ISVTX)),
+ target_name, th);
}
static int osd_mksym(struct osd_thread_info *info, struct osd_object *obj,
- struct lu_attr *attr, struct thandle *th)
+ struct lu_attr *attr, const char *target_name,
+ struct thandle *th)
{
LASSERT(S_ISLNK(attr->la_mode));
- return -EOPNOTSUPP;
+ LASSERT(target_name);
+ LASSERT(target_name[0] != 0);
+
+ CDEBUG(D_INODE, "I am going to symlink: "DFID3" to %s\n",
+ PFID3(lu_object_fid(&obj->oo_dt.do_lu)), target_name);
+ return osd_mkfile(info, obj, S_IFLNK, target_name, th);
}
static int osd_mknod(struct osd_thread_info *info, struct osd_object *obj,
- struct lu_attr *attr, struct thandle *th)
+ struct lu_attr *attr, const char *target_name,
+ struct thandle *th)
{
return -EOPNOTSUPP;
}
typedef int (*osd_obj_type_f)(struct osd_thread_info *, struct osd_object *,
- struct lu_attr *, struct thandle *);
+ struct lu_attr *, const char *target_name,
+ struct thandle *);
static osd_obj_type_f osd_create_type_f(__u32 mode)
{
}
static int osd_object_create(const struct lu_context *ctx, struct dt_object *dt,
- struct lu_attr *attr, struct thandle *th)
+ struct lu_attr *attr, const char *target_name,
+ struct thandle *th)
{
const struct lu_fid *fid = lu_object_fid(&dt->do_lu);
struct osd_object *obj = osd_dt_obj(dt);
result = osd_create_pre(info, obj, attr, th);
if (result == 0) {
result = osd_create_type_f(attr->la_mode & S_IFMT)(info, obj,
- attr, th);
+ attr,
+ target_name,
+ th);
if (result == 0)
result = osd_create_post(info, obj, attr, th);
}
return rc;
}
+static int osd_readlink(const struct lu_context *ctxt, struct dt_object *dt,
+ void *buf, int size)
+{
+ struct inode *inode = osd_dt_obj(dt)->oo_inode;
+ struct osd_thread_info *info = lu_context_key_get(ctxt, &osd_key);
+ struct dentry *dentry = &info->oti_dentry;
+ struct file *file;
+ mm_segment_t seg;
+ int rc;
+
+ LASSERT(lu_object_exists(ctxt, &dt->do_lu));
+ LASSERT(inode->i_op != NULL && inode->i_op->readlink != NULL);
+ LASSERT(buf != NULL);
+ dentry->d_inode = inode;
+
+ file = osd_rw_init(ctxt, inode, &seg);
+ rc = inode->i_op->readlink(dentry, buf, size);
+ osd_rw_fini(&seg);
+ return rc;
+
+}
+
static struct dt_object_operations osd_obj_ops = {
.do_lock = osd_object_lock,
.do_unlock = osd_object_unlock,
.do_ref_add = osd_object_ref_add,
.do_ref_del = osd_object_ref_del,
.do_xattr_get = osd_xattr_get,
+ .do_readlink = osd_readlink,
.do_xattr_set = osd_xattr_set,
.do_xattr_del = osd_xattr_del,
.do_xattr_list = osd_xattr_list,
* Body operations.
*/
-static struct file *osd_rw_init(const struct lu_context *ctxt,
- struct inode *inode, mm_segment_t *seg)
-{
- struct osd_thread_info *info = lu_context_key_get(ctxt, &osd_key);
- struct dentry *dentry = &info->oti_dentry;
- struct file *file = &info->oti_file;
-
- file->f_dentry = dentry;
- file->f_mapping = inode->i_mapping;
- file->f_op = inode->i_fop;
- file->f_mode = FMODE_WRITE|FMODE_READ;
- dentry->d_inode = inode;
-
- *seg = get_fs();
- set_fs(KERNEL_DS);
- return file;
-}
-
-static void osd_rw_fini(mm_segment_t *seg)
-{
- set_fs(*seg);
-}
-
static ssize_t osd_read(const struct lu_context *ctxt, struct dt_object *dt,
- char *buf, size_t count, loff_t *pos)
+ void *buf, size_t count, loff_t *pos)
{
struct inode *inode = osd_dt_obj(dt)->oo_inode;
struct file *file;
}
static int osd_write(const struct lu_context *ctxt, struct dt_object *dt,
- const char *buf, size_t count, loff_t *pos,
+ const void *buf, size_t count, loff_t *pos,
struct thandle *handle)
{
struct inode *inode = osd_dt_obj(dt)->oo_inode;
#endif
};
+static const struct req_msg_field *mds_readlink_server[] = {
+ &RMF_MDT_BODY,
+ &RMF_MDT_MD,
+};
+
static const struct req_format *req_formats[] = {
&RQF_MDS_CONNECT,
&RQF_MDS_DISCONNECT,
&RQF_MDS_CLOSE,
&RQF_MDS_PIN,
&RQF_MDS_READPAGE,
- &RQF_MDS_DONE_WRITING
+ &RQF_MDS_DONE_WRITING,
+ &RQF_MDS_READLINK
};
struct req_msg_field {
DEFINE_REQ_FMT0("MDS_GETATTR", mdt_body_only, mds_getattr_server);
EXPORT_SYMBOL(RQF_MDS_GETATTR);
+const struct req_format RQF_MDS_READLINK =
+ DEFINE_REQ_FMT0("MDS_READLINK", mdt_body_only, mds_readlink_server);
+EXPORT_SYMBOL(RQF_MDS_READLINK);
+
const struct req_format RQF_MDS_GETXATTR =
DEFINE_REQ_FMT0("MDS_GETXATTR",
mds_getxattr_client, mds_getxattr_server);
void req_capsule_set(struct req_capsule *pill, const struct req_format *fmt)
{
- LASSERT(pill->rc_fmt == NULL);
+// LASSERT(pill->rc_fmt == NULL);
LASSERT(__req_format_is_sane(fmt));
pill->rc_fmt = fmt;