From: huanghua Date: Tue, 1 Aug 2006 11:34:27 +0000 (+0000) Subject: added symlink operation support. X-Git-Tag: v1_8_0_110~486^2~1305 X-Git-Url: https://git.whamcloud.com/gitweb?a=commitdiff_plain;h=8d464f1b53519d086d9bd7a7b9803d8b817e6c05;p=fs%2Flustre-release.git added symlink operation support. --- diff --git a/lustre/cmm/cmm_object.c b/lustre/cmm/cmm_object.c index 6944976..585c342 100644 --- a/lustre/cmm/cmm_object.c +++ b/lustre/cmm/cmm_object.c @@ -247,6 +247,15 @@ static int cml_xattr_get(const struct lu_context *ctx, struct md_object *mo, 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) { @@ -320,6 +329,7 @@ static struct md_object_operations cml_mo_ops = { .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, @@ -546,6 +556,12 @@ static int cmr_xattr_get(const struct lu_context *ctx, struct md_object *mo, 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) { @@ -595,6 +611,7 @@ static struct md_object_operations cmr_mo_ops = { .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, diff --git a/lustre/include/dt_object.h b/lustre/include/dt_object.h index 7e0d283..487efda 100644 --- a/lustre/include/dt_object.h +++ b/lustre/include/dt_object.h @@ -201,12 +201,14 @@ struct dt_object_operations { 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 @@ -233,6 +235,9 @@ struct dt_object_operations { 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); }; /* diff --git a/lustre/include/lustre_req_layout.h b/lustre/include/lustre_req_layout.h index 3822717..892df93 100644 --- a/lustre/include/lustre_req_layout.h +++ b/lustre/include/lustre_req_layout.h @@ -95,6 +95,7 @@ extern const struct req_format RQF_MDS_SYNC; 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; diff --git a/lustre/include/md_object.h b/lustre/include/md_object.h index 36b9384..ca01d45 100644 --- a/lustre/include/md_object.h +++ b/lustre/include/md_object.h @@ -85,6 +85,10 @@ struct md_object_operations { 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 *); @@ -200,6 +204,13 @@ static inline int mo_attr_get(const struct lu_context *cx, struct md_object *m, 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) { diff --git a/lustre/mdd/mdd_handler.c b/lustre/mdd/mdd_handler.c index f5a8407..bc57919 100644 --- a/lustre/mdd/mdd_handler.c +++ b/lustre/mdd/mdd_handler.c @@ -173,6 +173,21 @@ static int mdd_xattr_get(const struct lu_context *ctxt, struct md_object *obj, 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) { @@ -406,6 +421,7 @@ static void mdd_trans_stop(const struct lu_context *ctxt, 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; @@ -415,7 +431,8 @@ static int __mdd_object_create(const struct lu_context *ctxt, 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; @@ -438,7 +455,7 @@ static int mdd_object_create(const struct lu_context *ctxt, 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); @@ -982,8 +999,7 @@ static int mdd_create(const struct lu_context *ctxt, struct md_object *pobj, * 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); @@ -1255,6 +1271,7 @@ static struct md_object_operations mdd_obj_ops = { .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, diff --git a/lustre/mdt/mdt_handler.c b/lustre/mdt/mdt_handler.c index 939a0abe..278436b 100644 --- a/lustre/mdt/mdt_handler.c +++ b/lustre/mdt/mdt_handler.c @@ -250,27 +250,19 @@ static int mdt_getattr_internal(struct mdt_thread_info *info, 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)) { @@ -296,11 +288,10 @@ skip_packing: 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); @@ -316,9 +307,12 @@ skip_packing: } } 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; @@ -326,9 +320,11 @@ skip_packing: 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) { @@ -336,9 +332,9 @@ skip_packing: 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) diff --git a/lustre/mdt/mdt_reint.c b/lustre/mdt/mdt_reint.c index d0390cd..48b3e02 100644 --- a/lustre/mdt/mdt_reint.c +++ b/lustre/mdt/mdt_reint.c @@ -466,6 +466,9 @@ static int mdt_reint_rename(struct mdt_thread_info *info) 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, @@ -485,6 +488,10 @@ static int mdt_reint_rename(struct mdt_thread_info *info) 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); diff --git a/lustre/osd/osd_handler.c b/lustre/osd/osd_handler.c index d5ae122..d4c5ede 100644 --- a/lustre/osd/osd_handler.c +++ b/lustre/osd/osd_handler.c @@ -237,6 +237,31 @@ static int osd_invariant(const struct osd_object *obj) #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) { @@ -619,7 +644,7 @@ static void osd_fid_build_name(const struct lu_fid *fid, char *name) } 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); @@ -643,7 +668,10 @@ static int osd_mkfile(struct osd_thread_info *info, struct osd_object *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; @@ -665,7 +693,8 @@ enum { }; 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; @@ -674,7 +703,7 @@ static int osd_mkdir(struct osd_thread_info *info, struct osd_object *obj, 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); /* @@ -688,28 +717,38 @@ static int osd_mkdir(struct osd_thread_info *info, struct osd_object *obj, } 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) { @@ -739,7 +778,8 @@ 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); @@ -767,7 +807,9 @@ static int osd_object_create(const struct lu_context *ctx, struct dt_object *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); } @@ -1032,6 +1074,28 @@ static int osd_readpage(const struct lu_context *ctxt, 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, @@ -1042,6 +1106,7 @@ static struct dt_object_operations osd_obj_ops = { .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, @@ -1052,31 +1117,8 @@ static struct dt_object_operations osd_obj_ops = { * 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; @@ -1094,7 +1136,7 @@ static ssize_t osd_read(const struct lu_context *ctxt, struct dt_object *dt, } 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; diff --git a/lustre/ptlrpc/layout.c b/lustre/ptlrpc/layout.c index 260815c..7dbef3a 100644 --- a/lustre/ptlrpc/layout.c +++ b/lustre/ptlrpc/layout.c @@ -221,6 +221,11 @@ static const struct req_msg_field *mds_getattr_server[] = { #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, @@ -249,7 +254,8 @@ static const struct req_format *req_formats[] = { &RQF_MDS_CLOSE, &RQF_MDS_PIN, &RQF_MDS_READPAGE, - &RQF_MDS_DONE_WRITING + &RQF_MDS_DONE_WRITING, + &RQF_MDS_READLINK }; struct req_msg_field { @@ -452,6 +458,10 @@ const struct req_format RQF_MDS_GETATTR = 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); @@ -631,7 +641,7 @@ static struct lustre_msg *__req_msg(const struct req_capsule *pill, 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;