.vop_nremove = vop_compat_nremove,
.vop_nrmdir = vop_compat_nrmdir,
.vop_nrename = vop_compat_nrename,
- .vop_mountctl = journal_mountctl
+ .vop_mountctl = vop_stdmountctl
};
VNODEOP_SET(default_vnode_vops);
return (0);
}
+int
+vop_stdmountctl(struct vop_mountctl_args *ap)
+{
+
+ struct mount *mp;
+ int error = 0;
+
+ mp = ap->a_head.a_ops->head.vv_mount;
+
+ switch(ap->a_op) {
+ case MOUNTCTL_MOUNTFLAGS:
+ /*
+ * Get a string buffer with all the mount flags
+ * names comman separated.
+ * mount(2) will use this information.
+ */
+ *ap->a_res = vfs_flagstostr(mp, ap->a_buf, ap->a_buflen,
+ &error);
+ break;
+ case MOUNTCTL_INSTALL_VFS_JOURNAL:
+ case MOUNTCTL_RESTART_VFS_JOURNAL:
+ case MOUNTCTL_REMOVE_VFS_JOURNAL:
+ case MOUNTCTL_RESYNC_VFS_JOURNAL:
+ case MOUNTCTL_STATUS_VFS_JOURNAL:
+ error = journal_mountctl(ap);
+ break;
+ default:
+ error = EOPNOTSUPP;
+ break;
+ }
+ return (error);
+}
+
int
vfs_stdroot(struct mount *mp, struct vnode **vpp)
{
#include <sys/thread2.h>
#include <sys/sysref2.h>
+/*
+ * Struct for mount options to printable formats.
+ */
+struct mountctl_opt {
+ int o_opt;
+ const char *o_name;
+};
+
static MALLOC_DEFINE(M_NETADDR, "Export Host", "Export host address structure");
int numvnodes;
}
/*
+ * Checks the mount flags for parameter mp and put the names comma-separated
+ * into a string buffer buf with a size limit specified by len.
+ *
+ * It returns the number of bytes written into buf, and (*errorp) will be
+ * set to 0, EINVAL (if passed length is 0), or ENOSPC (supplied buffer was
+ * not large enough). The buffer will be 0-terminated if len was not 0.
+ */
+#define OPTARYSIZE (sizeof(optnames) / sizeof(optnames[0]))
+
+size_t
+vfs_flagstostr(struct mount *mp, char *buf, size_t len, int *errorp)
+{
+ static const struct mountctl_opt optnames[] = {
+ { MNT_ASYNC, "asynchronous" },
+ { MNT_EXPORTED, "NFS exported" },
+ { MNT_LOCAL, "local" },
+ { MNT_NOATIME, "noatime" },
+ { MNT_NODEV, "nodev" },
+ { MNT_NOEXEC, "noexec" },
+ { MNT_NOSUID, "nosuid" },
+ { MNT_NOSYMFOLLOW, "nosymfollow" },
+ { MNT_QUOTA, "with-quotas" },
+ { MNT_RDONLY, "read-only" },
+ { MNT_SYNCHRONOUS, "synchronous" },
+ { MNT_UNION, "union" },
+ { MNT_NOCLUSTERR, "noclusterr" },
+ { MNT_NOCLUSTERW, "noclusterw" },
+ { MNT_SUIDDIR, "suiddir" },
+ { MNT_SOFTDEP, "soft-updates" },
+ { MNT_IGNORE, "ignore" }
+ };
+ const struct mountctl_opt *opt;
+ int flags;
+ int bwritten;
+ int bleft;
+ int optlen;
+
+ *errorp = 0;
+ flags = mp->mnt_flag & MNT_VISFLAGMASK;
+ bwritten = 0;
+ bleft = len - 1; /* leave room for trailing \0 */
+ if (bleft < 0) { /* degenerate case, 0-length buffer */
+ *errorp = EINVAL;
+ return(0);
+ }
+
+ for (opt = optnames; flags && opt < &optnames[OPTARYSIZE]; ++opt) {
+ if ((flags & opt->o_opt) == 0)
+ continue;
+ optlen = strlen(opt->o_name);
+ if (bwritten) {
+ if (bleft == 0) {
+ *errorp = ENOSPC;
+ break;
+ }
+ buf[bwritten++] = ',';
+ --bleft;
+ }
+ if (bleft < optlen) {
+ *errorp = ENOSPC;
+ break;
+ }
+ bcopy(opt->o_name, buf + bwritten, optlen);
+ bwritten += optlen;
+ bleft -= optlen;
+ }
+
+ /*
+ * Space already reserved for trailing \0
+ */
+ buf[bwritten] = 0;
+ return (bwritten);
+}
+
+#undef OPTARYSIZE
+
+/*
* Build hash lists of net addresses and hang them off the mount point.
* Called by ufs_mount() to set up the lists of export addresses.
*/
int vn_stat (struct vnode *vp, struct stat *sb, struct ucred *cred);
cdev_t vn_todev (struct vnode *vp);
void vfs_timestamp (struct timespec *);
+size_t vfs_flagstostr(struct mount *mp, char *buf, size_t len, int *errorp);
void vn_mark_atime(struct vnode *vp, struct thread *td);
int vn_writechk (struct vnode *vp, struct nchandle *nch);
int ncp_writechk(struct nchandle *nch);
int vop_stdopen (struct vop_open_args *ap);
int vop_stdclose (struct vop_close_args *ap);
+int vop_stdmountctl(struct vop_mountctl_args *ap);
int vop_stdgetpages(struct vop_getpages_args *ap);
int vop_stdputpages(struct vop_putpages_args *ap);
int vop_stdmarkatime(struct vop_markatime_args *ap);