+ struct md_op_data op_data = { { 0 } };
+ int rc;
+ ENTRY;
+
+ LASSERT(src);
+ LASSERT(tgt);
+
+ liblustre_wait_event(0);
+ llu_prep_md_op_data(&op_data, src, tgt, NULL, 0, 0,
+ LUSTRE_OPC_ANY);
+ rc = md_rename(llu_i2sbi(src)->ll_md_exp, &op_data,
+ oldname, oldnamelen, newname, newnamelen,
+ &request);
+ if (!rc) {
+ rc = llu_objects_destroy(request, src);
+ }
+
+ ptlrpc_req_finished(request);
+ liblustre_wait_idle();
+
+ RETURN(rc);
+}
+
+#ifdef _HAVE_STATVFS
+static int llu_statfs_internal(struct llu_sb_info *sbi,
+ struct obd_statfs *osfs, __u64 max_age)
+{
+ struct obd_statfs obd_osfs;
+ int rc;
+ ENTRY;
+
+ rc = obd_statfs(NULL, sbi->ll_md_exp, osfs, max_age, 0);
+ if (rc) {
+ CERROR("md_statfs fails: rc = %d\n", rc);
+ RETURN(rc);
+ }
+
+ CDEBUG(D_SUPER, "MDC blocks "LPU64"/"LPU64" objects "LPU64"/"LPU64"\n",
+ osfs->os_bavail, osfs->os_blocks, osfs->os_ffree,osfs->os_files);
+
+ rc = obd_statfs_rqset(class_exp2obd(sbi->ll_dt_exp),
+ &obd_statfs, max_age, 0);
+ if (rc) {
+ CERROR("obd_statfs fails: rc = %d\n", rc);
+ RETURN(rc);
+ }
+
+ CDEBUG(D_SUPER, "OSC blocks "LPU64"/"LPU64" objects "LPU64"/"LPU64"\n",
+ obd_osfs.os_bavail, obd_osfs.os_blocks, obd_osfs.os_ffree,
+ obd_osfs.os_files);
+
+ osfs->os_blocks = obd_osfs.os_blocks;
+ osfs->os_bfree = obd_osfs.os_bfree;
+ osfs->os_bavail = obd_osfs.os_bavail;
+
+ /* If we don't have as many objects free on the OST as inodes
+ * on the MDS, we reduce the total number of inodes to
+ * compensate, so that the "inodes in use" number is correct.
+ */
+ if (obd_osfs.os_ffree < osfs->os_ffree) {
+ osfs->os_files = (osfs->os_files - osfs->os_ffree) +
+ obd_osfs.os_ffree;
+ osfs->os_ffree = obd_osfs.os_ffree;
+ }
+
+ RETURN(rc);
+}
+
+static int llu_statfs(struct llu_sb_info *sbi, struct statfs *sfs)
+{
+ struct obd_statfs osfs;
+ int rc;
+
+ CDEBUG(D_VFSTRACE, "VFS Op:\n");
+
+ /* For now we will always get up-to-date statfs values, but in the
+ * future we may allow some amount of caching on the client (e.g.
+ * from QOS or lprocfs updates). */
+ rc = llu_statfs_internal(sbi, &osfs,
+ cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS));
+ if (rc)
+ return rc;
+
+ statfs_unpack(sfs, &osfs);
+
+ if (sizeof(sfs->f_blocks) == 4) {
+ while (osfs.os_blocks > ~0UL) {
+ sfs->f_bsize <<= 1;
+
+ osfs.os_blocks >>= 1;
+ osfs.os_bfree >>= 1;
+ osfs.os_bavail >>= 1;
+ }
+ }
+
+ sfs->f_blocks = osfs.os_blocks;
+ sfs->f_bfree = osfs.os_bfree;
+ sfs->f_bavail = osfs.os_bavail;
+
+ return 0;
+}
+
+static int llu_iop_statvfs(struct pnode *pno,
+ struct inode *ino,
+ struct intnl_statvfs *buf)
+{
+ struct statfs fs;
+ int rc;
+ ENTRY;
+
+ liblustre_wait_event(0);
+
+#ifndef __CYGWIN__
+ LASSERT(pno->p_base->pb_ino);
+ rc = llu_statfs(llu_i2sbi(pno->p_base->pb_ino), &fs);
+ if (rc)
+ RETURN(rc);
+
+ /* from native driver */
+ buf->f_bsize = fs.f_bsize; /* file system block size */
+ buf->f_frsize = fs.f_bsize; /* file system fundamental block size */
+ buf->f_blocks = fs.f_blocks;
+ buf->f_bfree = fs.f_bfree;
+ buf->f_bavail = fs.f_bavail;
+ buf->f_files = fs.f_files; /* Total number serial numbers */
+ buf->f_ffree = fs.f_ffree; /* Number free serial numbers */
+ buf->f_favail = fs.f_ffree; /* Number free ser num for non-privileged*/
+ buf->f_fsid = fs.f_fsid.__val[1];
+ buf->f_flag = 0; /* No equiv in statfs; maybe use type? */
+ buf->f_namemax = fs.f_namelen;
+#endif
+
+ liblustre_wait_event(0);
+ RETURN(0);
+}
+#endif /* _HAVE_STATVFS */
+
+static int llu_iop_mkdir_raw(struct pnode *pno, mode_t mode)
+{
+ struct inode *dir = pno->p_base->pb_parent->pb_ino;
+ struct qstr *qstr = &pno->p_base->pb_name;
+ const char *name = qstr->name;
+ int len = qstr->len;
+ struct ptlrpc_request *request = NULL;
+ struct intnl_stat *st = llu_i2stat(dir);
+ struct md_op_data op_data = {{ 0 }};
+ int err = -EMLINK;
+ ENTRY;
+
+ liblustre_wait_event(0);
+ CDEBUG(D_VFSTRACE, "VFS Op:name=%.*s,dir=%llu/%lu(%p)\n", len, name,
+ (long long)st->st_ino, llu_i2info(dir)->lli_st_generation, dir);
+
+ if (st->st_nlink >= EXT2_LINK_MAX)
+ RETURN(err);
+
+ llu_prep_md_op_data(&op_data, dir, NULL, name, len, 0,
+ LUSTRE_OPC_MKDIR);
+
+ err = md_create(llu_i2sbi(dir)->ll_md_exp, &op_data, NULL, 0,
+ mode | S_IFDIR, current->fsuid, current->fsgid,
+ cfs_curproc_cap_pack(), 0, &request);
+ ptlrpc_req_finished(request);
+ liblustre_wait_event(0);
+ RETURN(err);
+}
+
+static int llu_iop_rmdir_raw(struct pnode *pno)
+{
+ struct inode *dir = pno->p_base->pb_parent->pb_ino;
+ struct qstr *qstr = &pno->p_base->pb_name;
+ const char *name = qstr->name;
+ int len = qstr->len;
+ struct ptlrpc_request *request = NULL;
+ struct md_op_data op_data = {{ 0 }};
+ int rc;
+ ENTRY;
+
+ liblustre_wait_event(0);
+ CDEBUG(D_VFSTRACE, "VFS Op:name=%.*s,dir=%llu/%lu(%p)\n", len, name,
+ (long long)llu_i2stat(dir)->st_ino,
+ llu_i2info(dir)->lli_st_generation, dir);
+
+ llu_prep_md_op_data(&op_data, dir, NULL, name, len, S_IFDIR,
+ LUSTRE_OPC_ANY);
+ rc = md_unlink(llu_i2sbi(dir)->ll_md_exp, &op_data, &request);
+ ptlrpc_req_finished(request);
+
+ liblustre_wait_event(0);
+ RETURN(rc);
+}
+
+#ifdef O_DIRECT
+#define FCNTL_FLMASK (O_APPEND|O_NONBLOCK|O_ASYNC|O_DIRECT)
+#else
+#define FCNTL_FLMASK (O_APPEND|O_NONBLOCK|O_ASYNC)
+#endif
+#define FCNTL_FLMASK_INVALID (O_NONBLOCK|O_ASYNC)
+
+/* refer to ll_file_flock() for details */
+static int llu_file_flock(struct inode *ino,
+ int cmd,
+ struct file_lock *file_lock)
+{
+ struct llu_inode_info *lli = llu_i2info(ino);
+ struct ldlm_res_id res_id =
+ { .name = {fid_seq(&lli->lli_fid),
+ fid_oid(&lli->lli_fid),
+ fid_ver(&lli->lli_fid),
+ LDLM_FLOCK} };
+ struct ldlm_enqueue_info einfo = {
+ .ei_type = LDLM_FLOCK,
+ .ei_mode = 0,
+ .ei_cb_cp = ldlm_flock_completion_ast,
+ .ei_cbdata = file_lock,
+ };
+ struct intnl_stat *st = llu_i2stat(ino);
+ struct lustre_handle lockh = {0};
+ ldlm_policy_data_t flock;
+ __u64 flags = 0;
+ int rc;
+
+ CDEBUG(D_VFSTRACE, "VFS Op:inode=%llu file_lock=%p\n",
+ (unsigned long long)st->st_ino, file_lock);
+
+ flock.l_flock.pid = file_lock->fl_pid;
+ flock.l_flock.start = file_lock->fl_start;
+ flock.l_flock.end = file_lock->fl_end;
+
+ switch (file_lock->fl_type) {
+ case F_RDLCK:
+ einfo.ei_mode = LCK_PR;
+ break;
+ case F_UNLCK:
+ einfo.ei_mode = LCK_NL;
+ break;
+ case F_WRLCK:
+ einfo.ei_mode = LCK_PW;
+ break;
+ default:
+ CERROR("unknown fcntl lock type: %d\n", file_lock->fl_type);
+ LBUG();
+ }
+
+ switch (cmd) {
+ case F_SETLKW:
+#ifdef F_SETLKW64
+#if F_SETLKW64 != F_SETLKW
+ case F_SETLKW64:
+#endif
+#endif
+ flags = 0;
+ break;
+ case F_SETLK:
+#ifdef F_SETLK64
+#if F_SETLK64 != F_SETLK
+ case F_SETLK64:
+#endif
+#endif
+ flags = LDLM_FL_BLOCK_NOWAIT;
+ break;
+ case F_GETLK:
+#ifdef F_GETLK64
+#if F_GETLK64 != F_GETLK
+ case F_GETLK64:
+#endif
+#endif
+ flags = LDLM_FL_TEST_LOCK;
+ file_lock->fl_type = einfo.ei_mode;
+ break;
+ default:
+ CERROR("unknown fcntl cmd: %d\n", cmd);
+ LBUG();
+ }
+
+ CDEBUG(D_DLMTRACE, "inode=%llu, pid=%u, cmd=%d, flags=%#llx, mode=%u, "
+ "start="LPX64", end="LPX64"\n", (unsigned long long)st->st_ino,
+ flock.l_flock.pid, cmd, flags, einfo.ei_mode, flock.l_flock.start,
+ flock.l_flock.end);
+
+ {
+ struct lmv_obd *lmv;
+ struct obd_device *lmv_obd;
+ lmv_obd = class_exp2obd(llu_i2mdexp(ino));
+ lmv = &lmv_obd->u.lmv;
+
+ if (lmv->desc.ld_tgt_count < 1)
+ RETURN(rc = -ENODEV);
+
+ if (lmv->tgts[0] != NULL && lmv->tgts[0]->ltd_exp != NULL)
+ rc = ldlm_cli_enqueue(lmv->tgts[0]->ltd_exp, NULL,
+ &einfo, &res_id, &flock, &flags,
+ NULL, 0, LVB_T_NONE, &lockh, 0);
+ else
+ rc = -ENODEV;
+ }
+ RETURN(rc);
+}
+
+static int assign_type(struct file_lock *fl, int type)
+{
+ switch (type) {
+ case F_RDLCK:
+ case F_WRLCK:
+ case F_UNLCK:
+ fl->fl_type = type;
+ return 0;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int flock_to_posix_lock(struct inode *ino,
+ struct file_lock *fl,
+ struct flock *l)
+{
+ switch (l->l_whence) {
+ /* XXX: only SEEK_SET is supported in lustre */
+ case SEEK_SET:
+ fl->fl_start = 0;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ fl->fl_end = l->l_len - 1;
+ if (l->l_len < 0)
+ return -EINVAL;
+ if (l->l_len == 0)
+ fl->fl_end = OFFSET_MAX;
+
+ fl->fl_pid = getpid();
+ fl->fl_flags = FL_POSIX;
+ fl->fl_notify = NULL;
+ fl->fl_insert = NULL;
+ fl->fl_remove = NULL;
+ /* XXX: these fields can't be filled with suitable values,
+ but I think lustre doesn't use them.
+ */
+ fl->fl_owner = NULL;
+ fl->fl_file = NULL;
+
+ return assign_type(fl, l->l_type);
+}
+
+static int llu_fcntl_getlk(struct inode *ino, struct flock *flock)
+{
+ struct file_lock fl;
+ int error;
+
+ error = EINVAL;
+ if ((flock->l_type != F_RDLCK) && (flock->l_type != F_WRLCK))
+ goto out;
+
+ error = flock_to_posix_lock(ino, &fl, flock);
+ if (error)
+ goto out;
+
+ error = llu_file_flock(ino, F_GETLK, &fl);
+ if (error)
+ goto out;
+
+ flock->l_type = F_UNLCK;
+ if (fl.fl_type != F_UNLCK) {
+ flock->l_pid = fl.fl_pid;
+ flock->l_start = fl.fl_start;
+ flock->l_len = fl.fl_end == OFFSET_MAX ? 0:
+ fl.fl_end - fl.fl_start + 1;
+ flock->l_whence = SEEK_SET;
+ flock->l_type = fl.fl_type;
+ }
+
+out:
+ return error;
+}
+
+static int llu_fcntl_setlk(struct inode *ino, int cmd, struct flock *flock)
+{
+ struct file_lock fl;
+ int flags = llu_i2info(ino)->lli_open_flags + 1;
+ int error;
+
+ error = flock_to_posix_lock(ino, &fl, flock);
+ if (error)
+ goto out;
+ if (cmd == F_SETLKW)
+ fl.fl_flags |= FL_SLEEP;
+
+ error = -EBADF;
+ switch (flock->l_type) {
+ case F_RDLCK:
+ if (!(flags & FMODE_READ))
+ goto out;
+ break;
+ case F_WRLCK:
+ if (!(flags & FMODE_WRITE))
+ goto out;
+ break;
+ case F_UNLCK:
+ break;
+ default:
+ error = -EINVAL;
+ goto out;
+ }
+
+ error = llu_file_flock(ino, cmd, &fl);
+ if (error)
+ goto out;
+
+out:
+ return error;
+}
+
+static int llu_iop_fcntl(struct inode *ino, int cmd, va_list ap, int *rtn)
+{
+ struct llu_inode_info *lli = llu_i2info(ino);
+ long flags;
+ struct flock *flock;
+ long err = 0;
+
+ liblustre_wait_event(0);
+ switch (cmd) {
+ case F_GETFL:
+ *rtn = lli->lli_open_flags;
+ break;
+ case F_SETFL:
+ flags = va_arg(ap, long);
+ flags &= FCNTL_FLMASK;
+ if (flags & FCNTL_FLMASK_INVALID) {
+ LCONSOLE_ERROR_MSG(0x010, "liblustre does not support "
+ "the O_NONBLOCK or O_ASYNC flags. "
+ "Please fix your application.\n");
+ *rtn = -EINVAL;
+ err = EINVAL;
+ break;
+ }
+ lli->lli_open_flags = (int)(flags & FCNTL_FLMASK) |
+ (lli->lli_open_flags & ~FCNTL_FLMASK);
+ *rtn = 0;
+ break;
+ case F_GETLK:
+#ifdef F_GETLK64
+#if F_GETLK64 != F_GETLK
+ case F_GETLK64:
+#endif
+#endif
+ flock = va_arg(ap, struct flock *);
+ err = llu_fcntl_getlk(ino, flock);
+ *rtn = err? -1: 0;
+ break;
+ case F_SETLK:
+#ifdef F_SETLKW64
+#if F_SETLKW64 != F_SETLKW
+ case F_SETLKW64:
+#endif
+#endif
+ case F_SETLKW:
+#ifdef F_SETLK64
+#if F_SETLK64 != F_SETLK
+ case F_SETLK64:
+#endif
+#endif
+ flock = va_arg(ap, struct flock *);
+ err = llu_fcntl_setlk(ino, cmd, flock);
+ *rtn = err? -1: 0;
+ break;
+ default:
+ CERROR("unsupported fcntl cmd %x\n", cmd);
+ *rtn = -ENOSYS;
+ err = ENOSYS;
+ break;
+ }
+
+ liblustre_wait_event(0);
+ return err;
+}
+
+static int llu_get_grouplock(struct inode *inode, unsigned long arg)
+{
+ struct llu_inode_info *lli = llu_i2info(inode);
+ struct ll_file_data *fd = lli->lli_file_data;
+ int rc;
+ struct ccc_grouplock grouplock;
+ ENTRY;
+
+ if (fd->fd_flags & LL_FILE_IGNORE_LOCK) {
+ RETURN(-ENOTSUPP);
+ }
+ if (fd->fd_flags & LL_FILE_GROUP_LOCKED) {
+ RETURN(-EINVAL);
+ }
+ LASSERT(fd->fd_grouplock.cg_lock == NULL);
+
+ rc = cl_get_grouplock(cl_i2info(inode)->lli_clob,
+ arg, (lli->lli_open_flags & O_NONBLOCK),
+ &grouplock);
+
+ if (rc)
+ RETURN(rc);
+
+ fd->fd_flags |= LL_FILE_GROUP_LOCKED;
+ fd->fd_grouplock = grouplock;
+
+ RETURN(0);
+}
+
+int llu_put_grouplock(struct inode *inode, unsigned long arg)
+{
+ struct llu_inode_info *lli = llu_i2info(inode);
+ struct ll_file_data *fd = lli->lli_file_data;
+ struct ccc_grouplock grouplock;
+ ENTRY;
+
+ if (!(fd->fd_flags & LL_FILE_GROUP_LOCKED))
+ RETURN(-EINVAL);
+
+ LASSERT(fd->fd_grouplock.cg_lock != NULL);
+
+ if (fd->fd_grouplock.cg_gid != arg)
+ RETURN(-EINVAL);
+
+ grouplock = fd->fd_grouplock;
+ memset(&fd->fd_grouplock, 0, sizeof(fd->fd_grouplock));
+ fd->fd_flags &= ~LL_FILE_GROUP_LOCKED;
+
+ cl_put_grouplock(&grouplock);
+
+ RETURN(0);
+}
+
+static int llu_lov_dir_setstripe(struct inode *ino, unsigned long arg)
+{
+ struct llu_sb_info *sbi = llu_i2sbi(ino);
+ struct ptlrpc_request *request = NULL;
+ struct md_op_data op_data = {{ 0 }};
+ struct lov_user_md lum, *lump = (struct lov_user_md *)arg;
+ int rc = 0;
+
+ llu_prep_md_op_data(&op_data, ino, NULL, NULL, 0, 0,
+ LUSTRE_OPC_ANY);
+
+ LASSERT(sizeof(lum) == sizeof(*lump));
+ LASSERT(sizeof(lum.lmm_objects[0]) ==
+ sizeof(lump->lmm_objects[0]));
+ if (copy_from_user(&lum, lump, sizeof(lum)))
+ return(-EFAULT);
+
+ switch (lum.lmm_magic) {
+ case LOV_USER_MAGIC_V1: {
+ if (lum.lmm_magic != cpu_to_le32(LOV_USER_MAGIC_V1))
+ lustre_swab_lov_user_md_v1(&lum);
+ break;
+ }
+ case LOV_USER_MAGIC_V3: {
+ if (lum.lmm_magic != cpu_to_le32(LOV_USER_MAGIC_V3))
+ lustre_swab_lov_user_md_v3((struct lov_user_md_v3 *)&lum);
+ break;
+ }
+ default: {
+ CDEBUG(D_IOCTL, "bad userland LOV MAGIC:"
+ " %#08x != %#08x nor %#08x\n",
+ lum.lmm_magic, LOV_USER_MAGIC_V1,
+ LOV_USER_MAGIC_V3);
+ RETURN(-EINVAL);
+ }
+ }
+
+ /* swabbing is done in lov_setstripe() on server side */
+ rc = md_setattr(sbi->ll_md_exp, &op_data, &lum,
+ sizeof(lum), NULL, 0, &request, NULL);
+ if (rc) {
+ ptlrpc_req_finished(request);
+ if (rc != -EPERM && rc != -EACCES)
+ CERROR("md_setattr fails: rc = %d\n", rc);
+ return rc;
+ }
+ ptlrpc_req_finished(request);
+
+ return rc;
+}
+
+static int llu_lov_setstripe_ea_info(struct inode *ino, int flags,
+ struct lov_user_md *lum, int lum_size)
+{
+ struct llu_sb_info *sbi = llu_i2sbi(ino);
+ struct llu_inode_info *lli = llu_i2info(ino);
+ struct lookup_intent oit = {.it_op = IT_OPEN, .it_flags = flags};
+ struct ldlm_enqueue_info einfo = {
+ .ei_type = LDLM_IBITS,
+ .ei_mode = LCK_CR,
+ .ei_cb_bl = llu_md_blocking_ast,
+ .ei_cb_cp = ldlm_completion_ast,
+ };
+ struct ptlrpc_request *req = NULL;
+ struct lustre_md md;
+ struct md_op_data data = {{ 0 }};
+ struct lustre_handle lockh;
+ int rc = 0;
+ ENTRY;
+
+ if (lli->lli_has_smd) {
+ CDEBUG(D_IOCTL, "stripe already exists for ino "DFID"\n",
+ PFID(&lli->lli_fid));
+ return -EEXIST;
+ }
+
+ llu_prep_md_op_data(&data, NULL, ino, NULL, 0, O_RDWR,
+ LUSTRE_OPC_ANY);
+ rc = md_enqueue(sbi->ll_md_exp, &einfo, &oit, &data,
+ &lockh, lum, lum_size, NULL, LDLM_FL_INTENT_ONLY);
+ if (rc)
+ GOTO(out, rc);
+
+ req = oit.d.lustre.it_data;
+ rc = it_open_error(DISP_IT_EXECD, &oit);
+ if (rc) {
+ req->rq_replay = 0;
+ GOTO(out, rc);
+ }
+
+ rc = it_open_error(DISP_OPEN_OPEN, &oit);
+ if (rc) {
+ req->rq_replay = 0;
+ GOTO(out, rc);
+ }
+
+ rc = md_get_lustre_md(sbi->ll_md_exp, req,
+ sbi->ll_dt_exp, sbi->ll_md_exp, &md);
+ if (rc)
+ GOTO(out, rc);
+
+ llu_update_inode(ino, &md);
+ llu_local_open(lli, &oit);
+ /* release intent */
+ if (lustre_handle_is_used(&lockh))
+ ldlm_lock_decref(&lockh, LCK_CR);
+ ptlrpc_req_finished(req);
+ req = NULL;
+ rc = llu_file_release(ino);
+ EXIT;
+
+out:
+ if (req != NULL)
+ ptlrpc_req_finished(req);
+ return rc;
+}
+
+static int llu_lov_file_setstripe(struct inode *ino, unsigned long arg)
+{
+ struct lov_user_md lum, *lump = (struct lov_user_md *)arg;
+ int rc;
+ int flags = FMODE_WRITE;
+ ENTRY;
+
+ LASSERT(sizeof(lum) == sizeof(*lump));
+ LASSERT(sizeof(lum.lmm_objects[0]) == sizeof(lump->lmm_objects[0]));
+ if (copy_from_user(&lum, lump, sizeof(lum)))
+ RETURN(-EFAULT);
+
+ rc = llu_lov_setstripe_ea_info(ino, flags, &lum, sizeof(lum));
+ RETURN(rc);
+}
+
+static int llu_lov_setstripe(struct inode *ino, unsigned long arg)
+{
+ struct intnl_stat *st = llu_i2stat(ino);
+ if (S_ISREG(st->st_mode))
+ return llu_lov_file_setstripe(ino, arg);
+ if (S_ISDIR(st->st_mode))
+ return llu_lov_dir_setstripe(ino, arg);
+
+ return -EINVAL;
+}
+
+static int llu_lov_getstripe(struct inode *ino, unsigned long arg)
+{
+ struct lov_stripe_md *lsm = NULL;
+ int rc = -ENODATA;
+
+ lsm = ccc_inode_lsm_get(ino);
+ if (lsm != NULL)
+ rc = obd_iocontrol(LL_IOC_LOV_GETSTRIPE, llu_i2obdexp(ino), 0, lsm,
+ (void *)arg);
+ ccc_inode_lsm_put(ino, lsm);
+ return rc;
+}
+
+static int llu_iop_ioctl(struct inode *ino, unsigned long int request,
+ va_list ap)
+{
+ unsigned long arg;
+ int rc;
+
+ liblustre_wait_event(0);
+
+ switch (request) {
+ case LL_IOC_GROUP_LOCK:
+ arg = va_arg(ap, unsigned long);
+ rc = llu_get_grouplock(ino, arg);
+ break;
+ case LL_IOC_GROUP_UNLOCK:
+ arg = va_arg(ap, unsigned long);
+ rc = llu_put_grouplock(ino, arg);
+ break;
+ case LL_IOC_LOV_SETSTRIPE:
+ arg = va_arg(ap, unsigned long);
+ rc = llu_lov_setstripe(ino, arg);
+ break;
+ case LL_IOC_LOV_GETSTRIPE:
+ arg = va_arg(ap, unsigned long);
+ rc = llu_lov_getstripe(ino, arg);
+ break;
+ default:
+ CERROR("did not support ioctl cmd %lx\n", request);
+ rc = -ENOSYS;
+ break;
+ }
+
+ liblustre_wait_event(0);
+ return rc;
+}
+
+/*
+ * we already do syncronous read/write
+ */
+static int llu_iop_sync(struct inode *inode)
+{
+ liblustre_wait_event(0);
+ return 0;
+}
+
+static int llu_iop_datasync(struct inode *inode)
+{
+ liblustre_wait_event(0);
+ return 0;
+}
+
+static struct filesys_ops llu_filesys_ops = {
+ .fsop_gone = llu_fsop_gone,
+};
+
+struct inode *llu_iget(struct filesys *fs, struct lustre_md *md)
+{
+ struct inode *inode;
+ struct lu_fid fid;
+ struct file_identifier fileid = {&fid, sizeof(fid)};
+
+ if ((md->body->valid & (OBD_MD_FLID | OBD_MD_FLTYPE)) !=
+ (OBD_MD_FLID | OBD_MD_FLTYPE)) {
+ CERROR("bad md body valid mask "LPX64"\n", md->body->valid);
+ LBUG();
+ return ERR_PTR(-EPERM);
+ }
+
+ /* try to find existing inode */
+ fid = md->body->fid1;
+
+ inode = _sysio_i_find(fs, &fileid);
+ if (inode) {
+ if (inode->i_zombie/* ||
+ lli->lli_st_generation != md->body->generation*/) {
+ I_RELE(inode);
+ }
+ else {
+ llu_update_inode(inode, md);
+ return inode;
+ }
+ }
+
+ inode = llu_new_inode(fs, &fid);
+ if (inode)
+ llu_update_inode(inode, md);
+
+ return inode;
+}
+
+static int
+llu_fsswop_mount(const char *source,
+ unsigned flags,
+ const void *data __IS_UNUSED,
+ struct pnode *tocover,
+ struct mount **mntp)
+{
+ struct filesys *fs;
+ struct inode *root;
+ struct pnode_base *rootpb;
+ struct obd_device *obd;
+ struct llu_sb_info *sbi;
+ struct obd_statfs osfs;
+ static struct qstr noname = { NULL, 0, 0 };
+ struct ptlrpc_request *request = NULL;
+ struct lustre_md md;
+ class_uuid_t uuid;
+ struct config_llog_instance cfg = {0, };
+ struct lustre_profile *lprof;
+ char *zconf_mgsnid, *zconf_profile;
+ char *osc = NULL, *mdc = NULL;
+ int async = 1, err = -EINVAL;
+ struct obd_connect_data ocd = {0,};
+ struct md_op_data op_data = {{0}};
+ /* %p for void* in printf needs 16+2 characters: 0xffffffffffffffff */
+ const int instlen = sizeof(cfg.cfg_instance) * 2 + 2;