1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
5 * Module that interacts with the ZFS DMU and provides an abstraction
6 * to the rest of Lustre.
8 * Copyright (c) 2007 Cluster File Systems, Inc.
9 * Author: Alex Tomas <alex@clusterfs.com>
10 * Author: Atul Vidwansa <atul.vidwansa@sun.com>
11 * Author: Manoj Joseph <manoj.joseph@sun.com>
12 * Author: Mike Pershin <tappro@sun.com>
14 * This file is part of the Lustre file system, http://www.lustre.org
15 * Lustre is a trademark of Cluster File Systems, Inc.
17 * You may have signed or agreed to another license before downloading
18 * this software. If so, you are bound by the terms and conditions
19 * of that agreement, and the following does not apply to you. See the
20 * LICENSE file included with this distribution for more information.
22 * If you did not agree to a different license, then this copy of Lustre
23 * is open source software; you can redistribute it and/or modify it
24 * under the terms of version 2 of the GNU General Public License as
25 * published by the Free Software Foundation.
27 * In either case, Lustre is distributed in the hope that it will be
28 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
29 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 * license text for more details.
33 #include <sys/dnode.h>
37 #include <sys/statvfs.h>
39 #include <sys/spa_impl.h>
40 #include <sys/zfs_znode.h>
41 #include <sys/dmu_tx.h>
42 #include <sys/dmu_objset.h>
45 #include <sys/dnode.h>
46 #include <sys/dmu_ctl.h>
48 enum vtype iftovt_tab[] = {
49 VNON, VFIFO, VCHR, VNON, VDIR, VNON, VBLK, VNON,
50 VREG, VNON, VLNK, VNON, VSOCK, VNON, VNON, VNON
53 ushort_t vttoif_tab[] = {
54 0, S_IFREG, S_IFDIR, S_IFBLK, S_IFCHR, S_IFLNK, S_IFIFO,
55 S_IFDOOR, 0, S_IFSOCK, S_IFPORT, 0
58 #define MODEMASK 07777
60 #define IFTOVT(M) (iftovt_tab[((M) & S_IFMT) >> 12])
61 #define VTTOIF(T) (vttoif_tab[(int)(T)])
62 #define MAKEIMODE(T, M) (VTTOIF(T) | ((M) & ~S_IFMT))
65 * Debug levels. Default is LEVEL_CRITICAL.
67 #define LEVEL_CRITICAL 1
71 static int debug_level = LEVEL_CRITICAL;
73 #define CONFIG_DIR "/var/run/zfs/udmu"
75 static char configdir[MAXPATHLEN];
77 static void udmu_gethrestime(struct timespec *tp)
83 static void udmu_printf(int level, FILE *stream, char *message, ...)
87 if (level <= debug_level) {
88 va_start(args, message);
89 (void) vfprintf(stream, message, args);
94 void udmu_debug(int level)
101 char cmd[MAXPATHLEN];
102 struct rlimit rl = { 1024, 1024 };
106 * Set spa_config_dir to /var/run/zfs/udmu/$pid.
108 snprintf(configdir, MAXPATHLEN, "%s/%d", CONFIG_DIR, (int)getpid());
110 snprintf(cmd, MAXPATHLEN, "mkdir -p %s", configdir);
113 spa_config_dir = configdir;
115 (void) setvbuf(stdout, NULL, _IOLBF, 0);
116 (void) setrlimit(RLIMIT_NOFILE, &rl);
118 /* Initialize the emulation of kernel services in userland. */
119 kernel_init(FREAD | FWRITE);
121 rc = dctl_server_init(configdir, 2, 2);
123 fprintf(stderr, "Error calling dctl_server_init(): %i\n"
124 "lzpool and lzfs will not be functional!\n", rc);
131 rc = dctl_server_fini();
133 fprintf(stderr, "Error calling dctl_server_fini(): %i!\n", rc);
138 int udmu_objset_open(char *osname, char *import_dir, int import, int force,
142 char cmd[MAXPATHLEN];
144 uint64_t version = ZPL_VERSION;
145 int tried_import = FALSE;
147 memset(uos, 0, sizeof(udmu_objset_t));
149 c = strchr(osname, '/');
152 /* Let's try to open the objset */
153 error = dmu_objset_open(osname, DMU_OST_ZFS, DS_MODE_STANDARD,
156 if (error == ENOENT && import && !tried_import) {
157 /* objset not found, let's try to import the pool */
158 udmu_printf(LEVEL_INFO, stdout, "Importing pool %s\n", osname);
163 snprintf(cmd, sizeof(cmd), "lzpool import%s%s%s %s",
164 force ? " -F" : "", import_dir ? " -d " : "",
165 import_dir ? import_dir : "", osname);
173 udmu_printf(LEVEL_CRITICAL, stderr, "\"%s\" failed:"
174 " %d\n", cmd, error);
187 /* Check ZFS version */
188 error = zap_lookup(uos->os, MASTER_NODE_OBJ, ZPL_VERSION_STR, 8, 1,
191 udmu_printf(LEVEL_CRITICAL, stderr,
192 "Error looking up ZPL VERSION");
194 * We can't return ENOENT because that would mean the objset
199 } else if (version != LUSTRE_ZPL_VERSION) {
200 udmu_printf(LEVEL_CRITICAL, stderr,
201 "Mismatched versions: File system "
202 "is version %lld on-disk format, which is "
203 "incompatible with this software version %lld!",
204 (u_longlong_t)version, LUSTRE_ZPL_VERSION);
209 error = zap_lookup(uos->os, MASTER_NODE_OBJ, ZFS_ROOT_OBJ,
212 udmu_printf(LEVEL_CRITICAL, stderr,
213 "Error looking up ZFS root object.");
217 ASSERT(uos->root != 0);
221 if (uos->os == NULL && tried_import) {
224 spa_export(osname, NULL);
227 } else if(uos->os != NULL)
228 udmu_objset_close(uos, tried_import);
234 void udmu_wait_synced(udmu_objset_t *uos, dmu_tx_t *tx)
236 /* Wait for the pool to be synced */
237 txg_wait_synced(dmu_objset_pool(uos->os),
238 tx ? tx->tx_txg : 0ULL);
241 void udmu_objset_close(udmu_objset_t *uos, int export_pool)
244 char pool_name[MAXPATHLEN];
246 ASSERT(uos->os != NULL);
247 spa = uos->os->os->os_spa;
249 spa_config_enter(spa, RW_READER, FTAG);
250 strncpy(pool_name, spa_name(spa), sizeof(pool_name));
251 spa_config_exit(spa, FTAG);
253 udmu_wait_synced(uos, NULL);
254 /* close the object set */
255 dmu_objset_close(uos->os);
260 spa_export(pool_name, NULL);
263 int udmu_objset_statvfs(udmu_objset_t *uos, struct statvfs64 *statp)
265 uint64_t refdbytes, availbytes, usedobjs, availobjs;
267 dmu_objset_space(uos->os, &refdbytes, &availbytes, &usedobjs,
271 * The underlying storage pool actually uses multiple block sizes.
272 * We report the fragsize as the smallest block size we support,
273 * and we report our blocksize as the filesystem's maximum blocksize.
275 statp->f_frsize = 1ULL << SPA_MINBLOCKSHIFT;
276 statp->f_bsize = 1ULL << SPA_MAXBLOCKSHIFT;
279 * The following report "total" blocks of various kinds in the
280 * file system, but reported in terms of f_frsize - the
284 statp->f_blocks = (refdbytes + availbytes) >> SPA_MINBLOCKSHIFT;
285 statp->f_bfree = availbytes >> SPA_MINBLOCKSHIFT;
286 statp->f_bavail = statp->f_bfree; /* no root reservation */
289 * statvfs() should really be called statufs(), because it assumes
290 * static metadata. ZFS doesn't preallocate files, so the best
291 * we can do is report the max that could possibly fit in f_files,
292 * and that minus the number actually used in f_ffree.
293 * For f_ffree, report the smaller of the number of object available
294 * and the number of blocks (each object will take at least a block).
296 statp->f_ffree = MIN(availobjs, statp->f_bfree);
297 statp->f_favail = statp->f_ffree; /* no "root reservation" */
298 statp->f_files = statp->f_ffree + usedobjs;
300 /* ZFSFUSE: not necessary? see 'man statfs' */
301 /*(void) cmpldev(&d32, vfsp->vfs_dev);
302 statp->f_fsid = d32;*/
305 * We're a zfs filesystem.
307 /* ZFSFUSE: not necessary */
308 /*(void) strcpy(statp->f_basetype, vfssw[vfsp->vfs_fstype].vsw_name);
310 statp->f_flag = vf_to_stf(vfsp->vfs_flag);*/
312 statp->f_namemax = 256;
317 static int udmu_obj2dbuf(udmu_objset_t *uos, uint64_t oid, dmu_buf_t **dbp,
320 dmu_object_info_t doi;
325 err = dmu_bonus_hold(uos->os, oid, tag, dbp);
330 dmu_object_info_from_db(*dbp, &doi);
331 if (doi.doi_bonus_type != DMU_OT_ZNODE ||
332 doi.doi_bonus_size < sizeof (znode_phys_t)) {
333 dmu_buf_rele(*dbp, tag);
338 ASSERT((*dbp)->db_object == oid);
339 ASSERT((*dbp)->db_offset == -1);
340 ASSERT((*dbp)->db_data != NULL);
345 int udmu_objset_root(udmu_objset_t *uos, dmu_buf_t **dbp, void *tag)
347 return (udmu_obj2dbuf(uos, uos->root, dbp, tag));
350 int udmu_zap_lookup(udmu_objset_t *uos, dmu_buf_t *zap_db, const char *name,
351 void *value, int value_size, int intsize)
354 oid = zap_db->db_object;
357 * value_size should be a multiple of intsize.
358 * intsize is 8 for micro ZAP and 1, 2, 4 or 8 for a fat ZAP.
360 ASSERT(value_size % intsize == 0);
361 return (zap_lookup(uos->os, oid, name, intsize,
362 value_size / intsize, value));
366 * The transaction passed to this routine must have
367 * udmu_tx_hold_bonus(tx, DMU_NEW_OBJECT) called and then assigned
368 * to a transaction group.
370 void udmu_object_create(udmu_objset_t *uos, dmu_buf_t **dbp, dmu_tx_t *tx,
380 /* Assert that the transaction has been assigned to a
381 transaction group. */
382 ASSERT(tx->tx_txg != 0);
384 udmu_gethrestime(&now);
385 gen = dmu_tx_get_txg(tx);
387 /* Create a new DMU object. */
388 oid = dmu_object_alloc(uos->os, DMU_OT_PLAIN_FILE_CONTENTS, 0,
389 DMU_OT_ZNODE, sizeof (znode_phys_t), tx);
391 dmu_object_set_blocksize(uos->os, oid, 128ULL << 10, 0, tx);
393 VERIFY(0 == dmu_bonus_hold(uos->os, oid, tag, dbp));
395 dmu_buf_will_dirty(*dbp, tx);
397 /* Initialize the znode physical data to zero. */
398 ASSERT((*dbp)->db_size >= sizeof (znode_phys_t));
399 bzero((*dbp)->db_data, (*dbp)->db_size);
400 zp = (*dbp)->db_data;
403 ZFS_TIME_ENCODE(&now, zp->zp_crtime);
404 ZFS_TIME_ENCODE(&now, zp->zp_ctime);
405 ZFS_TIME_ENCODE(&now, zp->zp_atime);
406 ZFS_TIME_ENCODE(&now, zp->zp_mtime);
407 zp->zp_mode = MAKEIMODE(VREG, 0007);
412 * The transaction passed to this routine must have
413 * udmu_tx_hold_zap(tx, DMU_NEW_OBJECT, ...) called and then assigned
414 * to a transaction group.
416 void udmu_zap_create(udmu_objset_t *uos, dmu_buf_t **zap_dbp, dmu_tx_t *tx,
426 /* Assert that the transaction has been assigned to a
427 transaction group. */
428 ASSERT(tx->tx_txg != 0);
431 udmu_gethrestime(&now);
432 gen = dmu_tx_get_txg(tx);
434 oid = zap_create(uos->os, DMU_OT_DIRECTORY_CONTENTS, DMU_OT_ZNODE,
435 sizeof (znode_phys_t), tx);
437 VERIFY(0 == dmu_bonus_hold(uos->os, oid, tag, zap_dbp));
439 dmu_buf_will_dirty(*zap_dbp, tx);
441 bzero((*zap_dbp)->db_data, (*zap_dbp)->db_size);
442 zp = (*zap_dbp)->db_data;
446 zp->zp_mode = MAKEIMODE(VDIR, 0007);
448 ZFS_TIME_ENCODE(&now, zp->zp_crtime);
449 ZFS_TIME_ENCODE(&now, zp->zp_ctime);
450 ZFS_TIME_ENCODE(&now, zp->zp_atime);
451 ZFS_TIME_ENCODE(&now, zp->zp_mtime);
454 int udmu_object_get_dmu_buf(udmu_objset_t *uos, uint64_t object,
455 dmu_buf_t **dbp, void *tag)
457 return (udmu_obj2dbuf(uos, object, dbp, tag));
462 * The transaction passed to this routine must have
463 * udmu_tx_hold_bonus(tx, oid) and
464 * udmu_tx_hold_zap(tx, oid, ...)
465 * called and then assigned to a transaction group.
467 int udmu_zap_insert(udmu_objset_t *uos, dmu_buf_t *zap_db, dmu_tx_t *tx,
468 const char *name, void *value, int len)
470 uint64_t oid = zap_db->db_object;
472 /* Assert that the transaction has been assigned to a
473 transaction group. */
474 ASSERT(tx->tx_txg != 0);
476 dmu_buf_will_dirty(zap_db, tx);
477 return (zap_add(uos->os, oid, name, 8, 1, value, tx));
481 * The transaction passed to this routine must have
482 * udmu_tx_hold_zap(tx, oid, ...) called and then
483 * assigned to a transaction group.
485 int udmu_zap_delete(udmu_objset_t *uos, dmu_buf_t *zap_db, dmu_tx_t *tx,
488 uint64_t oid = zap_db->db_object;
490 /* Assert that the transaction has been assigned to a
491 transaction group. */
492 ASSERT(tx->tx_txg != 0);
494 return (zap_remove(uos->os, oid, name, tx));
498 * Read data from a DMU object
500 int udmu_object_read(udmu_objset_t *uos, dmu_buf_t *db, uint64_t offset,
501 uint64_t size, void *buf)
503 uint64_t oid = db->db_object;
507 udmu_printf(LEVEL_INFO, stdout, "udmu_read(%lld, %lld, %lld)\n",
510 udmu_object_getattr(db, &va);
511 if (offset + size > va.va_size) {
512 if (va.va_size < offset)
515 size = va.va_size - offset;
518 rc = dmu_read(uos->os, oid, offset, size, buf);
526 * Write data to a DMU object
528 * The transaction passed to this routine must have had
529 * udmu_tx_hold_write(tx, oid, offset, size) called and then
530 * assigned to a transaction group.
532 void udmu_object_write(udmu_objset_t *uos, dmu_buf_t *db, struct dmu_tx *tx,
533 uint64_t offset, uint64_t size, void *buf)
535 uint64_t oid = db->db_object;
537 udmu_printf(LEVEL_INFO, stdout, "udmu_write(%lld, %lld, %lld\n",
540 dmu_write(uos->os, oid, offset, size, buf, tx);
544 * Retrieve the attributes of a DMU object
546 void udmu_object_getattr(dmu_buf_t *db, vnattr_t *vap)
548 dnode_t *dn = ((dmu_buf_impl_t *)db)->db_dnode;
549 znode_phys_t *zp = db->db_data;
551 vap->va_mask = AT_ATIME | AT_MTIME | AT_CTIME | AT_MODE | AT_SIZE |
552 AT_UID | AT_GID | AT_TYPE | AT_NLINK | AT_RDEV;
553 vap->va_atime.tv_sec = zp->zp_atime[0];
554 vap->va_atime.tv_nsec = 0;
555 vap->va_mtime.tv_sec = zp->zp_mtime[0];
556 vap->va_mtime.tv_nsec = 0;
557 vap->va_ctime.tv_sec = zp->zp_ctime[0];
558 vap->va_ctime.tv_nsec = 0;
559 vap->va_mode = zp->zp_mode & MODEMASK;;
560 vap->va_size = zp->zp_size;
561 vap->va_uid = zp->zp_uid;
562 vap->va_gid = zp->zp_gid;
563 vap->va_type = IFTOVT((mode_t)zp->zp_mode);
564 vap->va_nlink = zp->zp_links;
565 vap->va_rdev = zp->zp_rdev;
567 vap->va_blksize = dn->dn_datablksz;
568 vap->va_blkbits = dn->dn_datablkshift;
569 /* in 512-bytes units*/
570 vap->va_nblocks = DN_USED_BYTES(dn->dn_phys) >> SPA_MINBLOCKSHIFT;
571 vap->va_mask |= AT_NBLOCKS | AT_BLKSIZE;
575 * Set the attributes of an object
577 * The transaction passed to this routine must have
578 * udmu_tx_hold_bonus(tx, oid) called and then assigned
579 * to a transaction group.
581 void udmu_object_setattr(dmu_buf_t *db, dmu_tx_t *tx, vnattr_t *vap)
583 znode_phys_t *zp = db->db_data;
584 uint_t mask = vap->va_mask;
586 /* Assert that the transaction has been assigned to a
587 transaction group. */
588 ASSERT(tx->tx_txg != 0);
594 dmu_buf_will_dirty(db, tx);
597 * Set each attribute requested.
598 * We group settings according to the locks they need to acquire.
600 * Note: you cannot set ctime directly, although it will be
601 * updated as a side-effect of calling this function.
605 zp->zp_mode = MAKEIMODE(vap->va_type, vap->va_mode);
608 zp->zp_uid = (uint64_t)vap->va_uid;
611 zp->zp_gid = (uint64_t)vap->va_gid;
614 zp->zp_size = vap->va_size;
617 ZFS_TIME_ENCODE(&vap->va_atime, zp->zp_atime);
620 ZFS_TIME_ENCODE(&vap->va_mtime, zp->zp_mtime);
623 ZFS_TIME_ENCODE(&vap->va_ctime, zp->zp_ctime);
626 zp->zp_links = vap->va_nlink;
630 * Punch/truncate an object
632 * IN: db - dmu_buf of the object to free data in.
633 * off - start of section to free.
634 * len - length of section to free (0 => to EOF).
636 * RETURN: 0 if success
637 * error code if failure
639 * The transaction passed to this routine must have
640 * udmu_tx_hold_bonus(tx, oid) and
641 * if off < size, udmu_tx_hold_free(tx, oid, off, len ? len : DMU_OBJECT_END)
642 * called and then assigned to a transaction group.
644 void udmu_object_punch(udmu_objset_t *uos, dmu_buf_t *db, dmu_tx_t *tx,
645 uint64_t off, uint64_t len)
647 znode_phys_t *zp = db->db_data;
648 uint64_t oid = db->db_object;
649 uint64_t end = off + len;
650 uint64_t size = zp->zp_size;
652 /* Assert that the transaction has been assigned to a
653 transaction group. */
654 ASSERT(tx->tx_txg != 0);
657 * Nothing to do if file already at desired length.
659 if (len == 0 && size == off) {
663 if (end > size || len == 0) {
675 VERIFY(0 == dmu_free_range(uos->os, oid, off, rlen, tx));
680 * Delete a DMU object
682 * The transaction passed to this routine must have
683 * udmu_tx_hold_free(tx, oid, 0, DMU_OBJECT_END) called
684 * and then assigned to a transaction group.
686 * This will release db and set it to NULL to prevent further dbuf releases.
688 int udmu_object_delete(udmu_objset_t *uos, dmu_buf_t **db, dmu_tx_t *tx,
692 uint64_t oid = (*db)->db_object;
694 /* Assert that the transaction has been assigned to a
695 transaction group. */
696 ASSERT(tx->tx_txg != 0);
698 udmu_object_put_dmu_buf(*db, tag);
701 error = dmu_object_free(uos->os, oid, tx);
707 * Get the object id from dmu_buf_t
709 uint64_t udmu_object_get_id(dmu_buf_t *db)
712 return (db->db_object);
715 int udmu_object_is_zap(dmu_buf_t *_db)
717 dmu_buf_impl_t *db = (dmu_buf_impl_t *) _db;
718 if (db->db_dnode->dn_type == DMU_OT_DIRECTORY_CONTENTS)
724 * Release the reference to a dmu_buf object.
726 void udmu_object_put_dmu_buf(dmu_buf_t *db, void *tag)
729 dmu_buf_rele(db, tag);
732 dmu_tx_t *udmu_tx_create(udmu_objset_t *uos)
734 return (dmu_tx_create(uos->os));
737 void udmu_tx_hold_write(dmu_tx_t *tx, uint64_t object, uint64_t off, int len)
739 dmu_tx_hold_write(tx, object, off, len);
742 void udmu_tx_hold_free(dmu_tx_t *tx, uint64_t object, uint64_t off,
745 dmu_tx_hold_free(tx, object, off, len);
748 void udmu_tx_hold_zap(dmu_tx_t *tx, uint64_t object, int add, char *name)
750 dmu_tx_hold_zap(tx, object, add, name);
753 void udmu_tx_hold_bonus(dmu_tx_t *tx, uint64_t object)
755 dmu_tx_hold_bonus(tx, object);
758 void udmu_tx_abort(dmu_tx_t *tx)
763 int udmu_tx_assign(dmu_tx_t *tx, uint64_t txg_how)
765 return (dmu_tx_assign(tx, txg_how));
768 void udmu_tx_wait(dmu_tx_t *tx)
773 void udmu_tx_commit(dmu_tx_t *tx)
778 /* commit callback API */
779 void * udmu_tx_cb_create(size_t bytes)
781 return dmu_tx_callback_data_create(bytes);
784 int udmu_tx_cb_add(dmu_tx_t *tx, void *func, void *data)
786 return dmu_tx_callback_commit_add(tx, func, data);
789 int udmu_tx_cb_destroy(void *data)
791 return dmu_tx_callback_data_destroy(data);
794 int udmu_indblk_overhead(dmu_buf_t *db, unsigned long *used,
795 unsigned long *overhead)
797 dnode_t *dn = ((dmu_buf_impl_t *)db)->db_dnode;
799 *overhead = (2 * (*used))/(1 << dn->dn_phys->dn_indblkshift);
804 int udmu_get_blocksize(dmu_buf_t *db, long *blksz)
806 dnode_t *dn = ((dmu_buf_impl_t *)db)->db_dnode;
808 *blksz = (dn->dn_datablksz);