#define i_atime i_stbuf.st_atime
#define i_mtime i_stbuf.st_mtime
#define i_ctime i_stbuf.st_ctime
-#define i_size i_stbuf.st_size
+/* use i_size_read() i_size_write() to access i_stbuf.st_size */
#define i_blocks i_stbuf.st_blocks
#define i_blksize i_stbuf.st_blksize
#define i_mode i_stbuf.st_mode
OBD_CONNECT_CANCELSET | OBD_CONNECT_AT | \
LRU_RESIZE_CONNECT_FLAG | OBD_CONNECT_CKSUM | \
OBD_CONNECT_CHANGE_QS | \
- OBD_CONNECT_OSS_CAPA | OBD_CONNECT_RMT_CLIENT | \
+ OBD_CONNECT_OSS_CAPA | \
+ OBD_CONNECT_RMT_CLIENT | \
OBD_CONNECT_RMT_CLIENT_FORCE | OBD_CONNECT_VBR | \
OBD_CONNECT_MDS | OBD_CONNECT_SKIP_ORPHAN | \
OBD_CONNECT_GRANT_SHRINK | OBD_CONNECT_FULL20 | \
#define MDS_INODELOCK_LOOKUP 0x000001 /* dentry, mode, owner, group */
#define MDS_INODELOCK_UPDATE 0x000002 /* size, links, timestamps */
#define MDS_INODELOCK_OPEN 0x000004 /* For opened files */
+#define MDS_INODELOCK_LAYOUT 0x000008 /* for layout */
-/* Do not forget to increase MDS_INODELOCK_MAXSHIFT when adding new bits */
+/* Do not forget to increase MDS_INODELOCK_MAXSHIFT when adding new bits
+ * XXX: MDS_INODELOCK_MAXSHIFT should be increased to 3 once the layout lock is
+ * supported */
#define MDS_INODELOCK_MAXSHIFT 2
/* This FULL lock is useful to take on unlink sort of operations */
#define MDS_INODELOCK_FULL ((1<<(MDS_INODELOCK_MAXSHIFT+1))-1)
#define IT_GETXATTR (1 << 7)
#define IT_EXEC (1 << 8)
#define IT_PIN (1 << 9)
+#define IT_LAYOUT (1 << 10)
static inline int it_to_lock_mode(struct lookup_intent *it)
{
/* CREAT needs to be tested before open (both could be set) */
if (it->it_op & IT_CREAT)
return LCK_CW;
- else if (it->it_op & (IT_READDIR | IT_GETATTR | IT_OPEN | IT_LOOKUP))
+ else if (it->it_op & (IT_READDIR | IT_GETATTR | IT_OPEN | IT_LOOKUP |
+ IT_LAYOUT))
return LCK_CR;
LASSERTF(0, "Invalid it_op: %d\n", it->it_op);
return "unlink";
case IT_GETXATTR:
return "getxattr";
+ case IT_LAYOUT:
+ return "layout";
default:
CERROR("Unknown intent %d\n", it);
return "UNKNOWN";
/* Make sure all the right bits are set in this lock we
are going to pass to client */
LASSERTF(lock->l_policy_data.l_inodebits.bits ==
- (MDS_INODELOCK_LOOKUP|MDS_INODELOCK_UPDATE),
+ (MDS_INODELOCK_LOOKUP | MDS_INODELOCK_UPDATE |
+ MDS_INODELOCK_LAYOUT),
"Inappropriate inode lock bits during "
"conversion " LPU64 "\n",
lock->l_policy_data.l_inodebits.bits);
{
}
+static inline loff_t i_size_read(struct inode *inode)
+{
+ return inode->i_stbuf.st_size;
+}
+
+static inline void i_size_write(struct inode *inode, loff_t i_sz)
+{
+ inode->i_stbuf.st_size = i_sz;
+}
#endif
} else {
/* Use old size assignment to avoid
* deadlock bz14138 & bz14326 */
- inode->i_size = body->size;
+ i_size_write(inode, body->size);
lli->lli_flags |= LLIF_MDS_SIZE_LOCK;
}
ldlm_lock_decref(&lockh, mode);
} else {
/* Use old size assignment to avoid
* deadlock bz14138 & bz14326 */
- inode->i_size = body->size;
+ i_size_write(inode, body->size);
CDEBUG(D_VFSTRACE, "inode=%lu, updating i_size %llu\n",
inode->i_ino, (unsigned long long)body->size);
unsigned long user_addr = (unsigned long)iov[seg].iov_base;
if (rw == READ) {
- if (file_offset >= inode->i_size)
+ if (file_offset >= i_size_read(inode))
break;
- if (file_offset + iov_left > inode->i_size)
- iov_left = inode->i_size - file_offset;
+ if (file_offset + iov_left > i_size_read(inode))
+ iov_left = i_size_read(inode) - file_offset;
}
while (iov_left > 0) {
if (rc)
RETURN(rc);
- if (it->it_op & (IT_LOOKUP | IT_GETATTR))
+ if (it->it_op & (IT_LOOKUP | IT_GETATTR | IT_LAYOUT))
rc = lmv_intent_lookup(exp, op_data, lmm, lmmsize, it,
flags, reqp, cb_blocking,
extra_lock_flags);
lmm = NULL;
} else if (it->it_op & IT_UNLINK)
req = mdc_intent_unlink_pack(exp, it, op_data);
- else if (it->it_op & (IT_GETATTR | IT_LOOKUP))
+ else if (it->it_op & (IT_GETATTR | IT_LOOKUP | IT_LAYOUT))
req = mdc_intent_getattr_pack(exp, it, op_data);
else if (it->it_op == IT_READDIR)
req = ldlm_enqueue_pack(exp);
} else if (it->it_op == IT_OPEN) {
LASSERT(!it_disposition(it, DISP_OPEN_CREATE));
} else {
- LASSERT(it->it_op & (IT_GETATTR | IT_LOOKUP));
+ LASSERT(it->it_op & (IT_GETATTR | IT_LOOKUP | IT_LAYOUT));
}
/* If we already have a matching lock, then cancel the new
mode = ldlm_revalidate_lock_handle(&lockh, bits);
} else {
fid_build_reg_res_name(fid, &res_id);
- policy.l_inodebits.bits = (it->it_op == IT_GETATTR) ?
- MDS_INODELOCK_UPDATE : MDS_INODELOCK_LOOKUP;
+ switch (it->it_op) {
+ case IT_GETATTR:
+ policy.l_inodebits.bits = MDS_INODELOCK_UPDATE;
+ break;
+ case IT_LAYOUT:
+ policy.l_inodebits.bits = MDS_INODELOCK_LAYOUT;
+ break;
+ default:
+ policy.l_inodebits.bits = MDS_INODELOCK_LOOKUP;
+ break;
+ }
mode = ldlm_lock_match(exp->exp_obd->obd_namespace,
LDLM_FL_BLOCK_GRANTED, &res_id,
LDLM_IBITS, &policy,
lockh.cookie = 0;
if (fid_is_sane(&op_data->op_fid2) &&
- (it->it_op & (IT_LOOKUP | IT_GETATTR))) {
+ (it->it_op & (IT_LOOKUP | IT_GETATTR | IT_LAYOUT))) {
/* We could just return 1 immediately, but since we should only
* be called in revalidate_it if we already have a lock, let's
* verify that. */
lh->mlh_reg_mode = lm;
lh->mlh_type = MDT_PDO_LOCK;
- if (name != NULL) {
+ if (name != NULL && (name[0] != '\0')) {
LASSERT(namelen > 0);
lh->mlh_pdo_hash = full_name_hash(name, namelen);
} else {
name = NULL;
CDEBUG(D_INODE, "getattr with lock for "DFID"/"DFID", "
"ldlm_rep = %p\n",
- PFID(mdt_object_fid(parent)), PFID(&reqbody->fid2),
- ldlm_rep);
+ PFID(mdt_object_fid(parent)),
+ PFID(&reqbody->fid2), ldlm_rep);
} else {
lname = mdt_name(info->mti_env, (char *)name, namelen);
CDEBUG(D_INODE, "getattr with lock for "DFID"/%s, "
}
if (lname) {
- /* step 1: lock parent */
- lhp = &info->mti_lh[MDT_LH_PARENT];
- mdt_lock_pdo_init(lhp, LCK_PR, name, namelen);
- rc = mdt_object_lock(info, parent, lhp, MDS_INODELOCK_UPDATE,
- MDT_LOCAL_LOCK);
- if (unlikely(rc != 0))
- RETURN(rc);
+ /* step 1: lock parent only if parent is a directory */
+ if (S_ISDIR(lu_object_attr(&parent->mot_obj.mo_lu))) {
+ lhp = &info->mti_lh[MDT_LH_PARENT];
+ mdt_lock_pdo_init(lhp, LCK_PR, name, namelen);
+ rc = mdt_object_lock(info, parent, lhp,
+ MDS_INODELOCK_UPDATE,
+ MDT_LOCAL_LOCK);
+ if (unlikely(rc != 0))
+ RETURN(rc);
+ }
/* step 2: lookup child's fid by name */
rc = mdo_lookup(info->mti_env, next, lname, child_fid,
if (rc != 0) {
if (rc == -ENOENT)
- mdt_set_disposition(info, ldlm_rep, DISP_LOOKUP_NEG);
+ mdt_set_disposition(info, ldlm_rep,
+ DISP_LOOKUP_NEG);
GOTO(out_parent, rc);
} else
mdt_set_disposition(info, ldlm_rep, DISP_LOOKUP_POS);
relock:
OBD_FAIL_TIMEOUT(OBD_FAIL_MDS_RESEND, obd_timeout*2);
mdt_lock_handle_init(lhc);
- mdt_lock_reg_init(lhc, LCK_PR);
+ if (child_bits == MDS_INODELOCK_LAYOUT)
+ mdt_lock_reg_init(lhc, LCK_CR);
+ else
+ mdt_lock_reg_init(lhc, LCK_PR);
if (!(child_bits & MDS_INODELOCK_UPDATE)) {
struct md_attr *ma = &info->mti_attr;
if (unlikely(rc != 0))
GOTO(out_child, rc);
+ /* layout lock is used only on regular files */
+ if ((ma->ma_valid & MA_INODE) &&
+ (ma->ma_attr.la_valid & LA_MODE) &&
+ !S_ISREG(ma->ma_attr.la_mode))
+ child_bits &= ~MDS_INODELOCK_LAYOUT;
+
/* If the file has not been changed for some time, we
* return not only a LOOKUP lock, but also an UPDATE
* lock and this might save us RPC on later STAT. For
MDT_IT_UNLINK,
MDT_IT_TRUNC,
MDT_IT_GETXATTR,
+ MDT_IT_LAYOUT,
MDT_IT_NR
};
.it_fmt = NULL,
.it_flags = 0,
.it_act = NULL
+ },
+ [MDT_IT_LAYOUT] = {
+ .it_fmt = &RQF_LDLM_INTENT_GETATTR,
+ .it_flags = HABEO_REFERO,
+ .it_act = mdt_intent_getattr
}
};
case MDT_IT_GETATTR:
child_bits = MDS_INODELOCK_LOOKUP | MDS_INODELOCK_UPDATE;
break;
+ case MDT_IT_LAYOUT: {
+ static int printed = 0;
+
+ if (!printed) {
+ CERROR("layout lock not supported by this version\n");
+ printed = 1;
+ }
+ GOTO(out_shrink, rc = -EINVAL);
+ break;
+ }
default:
- CERROR("Unhandled till now");
+ CERROR("Unsupported intent (%d)\n", opcode);
GOTO(out_shrink, rc = -EINVAL);
}
case IT_GETXATTR:
rc = MDT_IT_GETXATTR;
break;
+ case IT_LAYOUT:
+ rc = MDT_IT_LAYOUT;
+ break;
default:
CERROR("Unknown intent opcode: %ld\n", itcode);
rc = -EINVAL;
newvalid |= OBD_MD_FLCTIME;
}
if (valid & OBD_MD_FLSIZE) {
- dst->o_size = src->i_size;
+ dst->o_size = i_size_read(src);
newvalid |= OBD_MD_FLSIZE;
}
if (valid & OBD_MD_FLBLOCKS) { /* allocation of space (x512 bytes) */
} else {
/* Use these existing objects if they are
* zero length. */
- if (dchild->d_inode->i_size == 0) {
+ if (i_size_read(dchild->d_inode) == 0) {
rc = filter_use_existing_obj(obd,dchild,
&handle, &cleanup_phase);
if (rc == 0)
MDS_INODELOCK_UPDATE);
LASSERTF(MDS_INODELOCK_OPEN == 0x000004, "found 0x%.8x\n",
MDS_INODELOCK_OPEN);
+ LASSERTF(MDS_INODELOCK_LAYOUT == 0x000008, "found 0x%.8x\n",
+ MDS_INODELOCK_LAYOUT);
/* Checks for struct mdt_ioepoch */
LASSERTF((int)sizeof(struct mdt_ioepoch) == 24, "found %lld\n",
CHECK_DEFINE_X(MDS_INODELOCK_LOOKUP);
CHECK_DEFINE_X(MDS_INODELOCK_UPDATE);
CHECK_DEFINE_X(MDS_INODELOCK_OPEN);
+ CHECK_DEFINE_X(MDS_INODELOCK_LAYOUT);
}
static void
MDS_INODELOCK_UPDATE);
LASSERTF(MDS_INODELOCK_OPEN == 0x000004, "found 0x%.8x\n",
MDS_INODELOCK_OPEN);
+ LASSERTF(MDS_INODELOCK_LAYOUT == 0x000008, "found 0x%.8x\n",
+ MDS_INODELOCK_LAYOUT);
/* Checks for struct mdt_ioepoch */
LASSERTF((int)sizeof(struct mdt_ioepoch) == 24, "found %lld\n",