1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License, Version 1.0 only
   6  * (the "License").  You may not use this file except in compliance
   7  * with the License.
   8  *
   9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  10  * or http://www.opensolaris.org/os/licensing.
  11  * See the License for the specific language governing permissions
  12  * and limitations under the License.
  13  *
  14  * When distributing Covered Code, include this CDDL HEADER in each
  15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  16  * If applicable, add the following below this CDDL HEADER, with the
  17  * fields enclosed by brackets "[]" replaced with your own identifying
  18  * information: Portions Copyright [yyyy] [name of copyright owner]
  19  *
  20  * CDDL HEADER END
  21  */
  22 /*
  23  * Copyright 2014 Garrett D'Amore <garrett@damore.org>
  24  *
  25  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
  26  * Use is subject to license terms.
  27  */
  28 
  29 #ifndef _SYS_FS_CACHEFS_DLOG_H
  30 #define _SYS_FS_CACHEFS_DLOG_H
  31 
  32 #include <sys/vfs.h>
  33 #include <sys/acl.h>
  34 
  35 #ifdef __cplusplus
  36 extern "C" {
  37 #endif
  38 
  39 /*
  40  * Version number of log file format.
  41  * Put in an int at the start of the file.
  42  * Large Files: Increment VER by 1.
  43  */
  44 #define CFS_DLOG_VERSION 1001
  45 
  46 /* valid types of dlog records */
  47 enum cfs_dlog_op {
  48         CFS_DLOG_CREATE = 0x100,
  49         CFS_DLOG_REMOVE,
  50         CFS_DLOG_LINK,
  51         CFS_DLOG_RENAME,
  52         CFS_DLOG_MKDIR,
  53         CFS_DLOG_RMDIR,
  54         CFS_DLOG_SYMLINK,
  55         CFS_DLOG_SETATTR,
  56         CFS_DLOG_SETSECATTR,
  57         CFS_DLOG_MODIFIED,
  58         CFS_DLOG_MAPFID,
  59         CFS_DLOG_TRAILER
  60 };
  61 typedef enum cfs_dlog_op cfs_dlog_op_t;
  62 
  63 /* validity of records */
  64 enum cfs_dlog_val {
  65         CFS_DLOG_VAL_CRASH = 0x200,     /* crash during record creation */
  66         CFS_DLOG_VAL_COMMITTED,         /* valid record */
  67         CFS_DLOG_VAL_ERROR,             /* error, operation not performed */
  68         CFS_DLOG_VAL_PROCESSED          /* record processed */
  69 };
  70 typedef enum cfs_dlog_val cfs_dlog_val_t;
  71 
  72 /* number of bytes for groups appended to a cred structure */
  73 #define CFS_DLOG_BUFSIZE (sizeof (gid_t) * (NGROUPS_MAX_DEFAULT - 1))
  74 
  75 /* the old kernel credential; ossified on disk so we're stuck with this. */
  76 typedef struct dl_cred {
  77         uint_t  __ign1;                 /* ignore (was ref count) */
  78         uid_t   cr_uid;                 /* effective user id */
  79         gid_t   cr_gid;                 /* effective group id */
  80         uid_t   cr_ruid;                /* real user id */
  81         gid_t   cr_rgid;                /* real group id */
  82         uid_t   cr_suid;                /* "saved" user id (from exec) */
  83         gid_t   cr_sgid;                /* "saved" group id (from exec) */
  84         uint_t  cr_ngroups;             /* number of groups in cr_groups */
  85         gid_t   cr_groups[1];           /* supplementary group list */
  86 } dl_cred_t;
  87 
  88 /*
  89  * cfs_dlog_mapping_space is stored on disk, so it needs to be the same
  90  * 32-bit vs. 64-bit. The other structures below are also stored on disk,
  91  * but they do not contain any 64-bit elements.
  92  */
  93 
  94 #if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4
  95 #pragma pack(4)
  96 #endif
  97 
  98 /* the basic elements in the mapping file */
  99 struct cfs_dlog_mapping_space {
 100         cfs_cid_t       ms_cid;         /* mapping key */
 101         off_t           ms_fid;         /* offset to fid */
 102         off_t           ms_times;       /* offset to timestamps */
 103 };
 104 
 105 #if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4
 106 #pragma pack()
 107 #endif
 108 
 109 /*
 110  * XX64: For now we use the old time_t defs. In the next version the logs
 111  * and on-disk structs may change to 64-bit. The structs here are used
 112  * for the data log.
 113  */
 114 /* mtime and ctime stamps */
 115 struct cfs_dlog_tm {
 116         cfs_timestruc_t tm_mtime;       /* cached mtime on file */
 117         cfs_timestruc_t tm_ctime;       /* cached ctime on file */
 118 };
 119 typedef struct cfs_dlog_tm cfs_dlog_tm_t;
 120 
 121 /* structure populated for setattr */
 122 struct cfs_dlog_setattr {
 123         cfs_vattr_t     dl_attrs;       /* attrs to set file to */
 124         int             dl_flags;       /* flags used with setattr */
 125         cfs_cid_t       dl_cid;         /* cid of the file to setattr */
 126         cfs_dlog_tm_t   dl_times;       /* ctime and mtime on file */
 127         dl_cred_t       dl_cred;        /* creds used */
 128         char            dl_buffer[CFS_DLOG_BUFSIZE];    /* groups */
 129 };
 130 
 131 /* structure for setsecattr (aka setting an ACL) */
 132 /* n.b. data for this can exceed sizeof this struct, due to 24k ACLs! */
 133 struct cfs_dlog_setsecattr {
 134         cfs_cid_t       dl_cid;         /* cid of file to setsecattr */
 135         cfs_dlog_tm_t   dl_times;       /* ctime and mtime on file */
 136         uint_t          dl_mask;        /* mask field in vsecattr_t */
 137         int             dl_aclcnt;      /* count of ACLs */
 138         int             dl_dfaclcnt;    /* count of default ACLs */
 139         dl_cred_t       dl_cred;        /* creds used */
 140         char            dl_buffer[CFS_DLOG_BUFSIZE]; /* groups + ACLs */
 141 };
 142 
 143 /* structure populated for creates */
 144 struct cfs_dlog_create {
 145         cfs_cid_t       dl_parent_cid;  /* parent directory cid */
 146         cfs_cid_t       dl_new_cid;     /* cid of the created file */
 147         cfs_vattr_t     dl_attrs;       /* attrs to create with */
 148         int             dl_excl;        /* exclusive mode flag */
 149         int             dl_mode;        /* mode bits for created file */
 150         int             dl_exists;      /* does file already exist? */
 151         cfs_dlog_tm_t   dl_times;       /* ctime and mtime on file */
 152         cfs_fid_t       dl_fid;         /* blank fid */
 153         dl_cred_t       dl_cred;        /* user credentials */
 154         char            dl_buffer[CFS_DLOG_BUFSIZE + MAXNAMELEN];
 155 };
 156 
 157 /* struct used for remove */
 158 struct cfs_dlog_remove {
 159         cfs_cid_t       dl_parent_cid;  /* parent directory cid */
 160         cfs_cid_t       dl_child_cid;   /* cid of entry that was removed */
 161         cfs_dlog_tm_t   dl_times;       /* ctime and mtime on file */
 162         dl_cred_t       dl_cred;        /* credentials to use */
 163         char            dl_buffer[CFS_DLOG_BUFSIZE + MAXNAMELEN];
 164 };
 165 
 166 /* struct used for rmdir */
 167 struct cfs_dlog_rmdir {
 168         cfs_cid_t       dl_parent_cid;  /* parent directory cid */
 169         dl_cred_t       dl_cred;        /* credentials to use */
 170         char            dl_buffer[CFS_DLOG_BUFSIZE + MAXNAMELEN];
 171 };
 172 
 173 /* struct used for mkdir */
 174 struct cfs_dlog_mkdir {
 175         cfs_cid_t       dl_parent_cid;  /* parent directory cid */
 176         cfs_cid_t       dl_child_cid;   /* cid of created entry */
 177         cfs_vattr_t     dl_attrs;       /* attrs to insert with */
 178         cfs_fid_t       dl_fid;         /* blank fid */
 179         dl_cred_t       dl_cred;        /* credentials to use */
 180         char            dl_buffer[CFS_DLOG_BUFSIZE + MAXNAMELEN];
 181 };
 182 
 183 /* struct used for link */
 184 struct cfs_dlog_link {
 185         cfs_cid_t       dl_parent_cid;  /* parent directory cid */
 186         cfs_cid_t       dl_child_cid;   /* cid of created entry */
 187         cfs_dlog_tm_t   dl_times;       /* ctime and mtime on file */
 188         dl_cred_t       dl_cred;        /* credentials to use */
 189         char            dl_buffer[CFS_DLOG_BUFSIZE + MAXNAMELEN];
 190 };
 191 
 192 /* struct used for symlink */
 193 struct cfs_dlog_symlink {
 194         cfs_cid_t       dl_parent_cid;  /* parent directory cid */
 195         cfs_cid_t       dl_child_cid;   /* cid of created entry */
 196         cfs_vattr_t     dl_attrs;       /* attrs to insert with */
 197         cfs_dlog_tm_t   dl_times;       /* ctime and mtime on file */
 198         cfs_fid_t       dl_fid;         /* blank fid */
 199         dl_cred_t       dl_cred;        /* credentials to use */
 200         char            dl_buffer[CFS_DLOG_BUFSIZE + MAXNAMELEN + MAXPATHLEN];
 201 };
 202 
 203 struct cfs_dlog_rename {
 204         cfs_cid_t       dl_oparent_cid; /* cid of the original parent dir */
 205         cfs_cid_t       dl_nparent_cid; /* cid of the new parent dir */
 206         cfs_cid_t       dl_child_cid;   /* cid of renamed file */
 207         cfs_dlog_tm_t   dl_times;       /* ctime and mtime on file */
 208         cfs_cid_t       dl_del_cid;     /* cid of deleted file */
 209         cfs_dlog_tm_t   dl_del_times;   /* ctime and mtime on deleted file */
 210         dl_cred_t       dl_cred;        /* credentials to use */
 211         char            dl_buffer[CFS_DLOG_BUFSIZE + (2 * MAXNAMELEN)];
 212 };
 213 
 214 struct cfs_dlog_modify {
 215         cfs_cid_t       dl_cid;         /* cid of modified file */
 216         cfs_dlog_tm_t   dl_times;       /* ctime and mtime on file */
 217         off32_t         dl_next;        /* daemon links modifies together */
 218         dl_cred_t       dl_cred;        /* credentials to use */
 219         char            dl_buffer[CFS_DLOG_BUFSIZE];    /* groups */
 220 };
 221 
 222 struct cfs_dlog_mapfid {
 223         cfs_cid_t       dl_cid;         /* cid of file */
 224         cfs_fid_t       dl_fid;         /* fid of file */
 225 };
 226 
 227 #define COMMON_RECORD_HDR()                                             \
 228         int             dl_len;         /* length of this record */     \
 229         cfs_dlog_op_t   dl_op;          /* operation */                 \
 230         cfs_dlog_val_t  dl_valid;       /* validity of operation */     \
 231         uint_t          dl_seq;         /* sequence number */
 232 
 233 /*
 234  * The trailer record must look just like the beginning of a record.
 235  * This allows the cachefs daemon to throw it away(not process the record)
 236  * with very little additional code.
 237  */
 238 struct cfs_dlog_trailer {
 239         COMMON_RECORD_HDR()
 240 };
 241 
 242 struct cfs_dlog_entry {
 243         COMMON_RECORD_HDR()
 244 
 245         union cfs_dlog_entry_items {
 246                 struct cfs_dlog_setattr         dl_setattr;
 247                 struct cfs_dlog_setsecattr      dl_setsecattr;
 248                 struct cfs_dlog_create          dl_create;
 249                 struct cfs_dlog_remove          dl_remove;
 250                 struct cfs_dlog_rmdir           dl_rmdir;
 251                 struct cfs_dlog_mkdir           dl_mkdir;
 252                 struct cfs_dlog_link            dl_link;
 253                 struct cfs_dlog_symlink         dl_symlink;
 254                 struct cfs_dlog_rename          dl_rename;
 255                 struct cfs_dlog_modify          dl_modify;
 256                 struct cfs_dlog_mapfid          dl_mapfid;
 257         } dl_u;
 258 
 259         struct cfs_dlog_trailer dl_trailer;
 260 };
 261 typedef struct cfs_dlog_entry cfs_dlog_entry_t;
 262 
 263 /*
 264  * XXXX the maxsize calculation below will give wrong answer if
 265  * the total size of struct cfs_dlog_setsecattr + max aclsize is less than
 266  * the size of the union above. This is currently true, but to be on the safe
 267  * side, use struct size plus acl size (minus trailer because it's not
 268  * not counted in the length field).
 269  */
 270 #define CFS_DLOG_SECATTR_MAXSIZE (sizeof (struct cfs_dlog_setsecattr) + \
 271         (sizeof (aclent_t) * MAX_ACL_ENTRIES))
 272 
 273 #ifndef MAX
 274 #define MAX(a, b)       (((a) > (b)) ? (a) : (b))
 275 #endif /* MAX */
 276 
 277 #define CFS_DLOG_ENTRY_MAXSIZE  \
 278         MAX(offsetof(struct cfs_dlog_entry, dl_trailer),                \
 279             offsetof(struct cfs_dlog_entry, dl_u.dl_setsecattr) +       \
 280             CFS_DLOG_SECATTR_MAXSIZE)
 281 
 282 #if defined(_KERNEL)
 283 int cachefs_dlog_setup(fscache_t *fscp, int createfile);
 284 void cachefs_dlog_teardown(fscache_t *fscp);
 285 int cachefs_dlog_commit(fscache_t *fscp, off_t offset, int error);
 286 int cachefs_dlog_cidmap(fscache_t *fscp);
 287 off_t cachefs_dlog_setattr(fscache_t *fscp, struct vattr *vap, int flags,
 288     cnode_t *cp, cred_t *cr);
 289 off_t
 290 cachefs_dlog_setsecattr(fscache_t *fscp, vsecattr_t *vsec, int flags,
 291     cnode_t *cp, cred_t *cr);
 292 off_t cachefs_dlog_create(fscache_t *fscp, cnode_t *pcp, char *nm,
 293     vattr_t *vap, int excl, int mode, cnode_t *cp, int exists, cred_t *cr);
 294 off_t cachefs_dlog_remove(fscache_t *fscp, cnode_t *pcp, char *nm, cnode_t *cp,
 295     cred_t *cr);
 296 off_t cachefs_dlog_link(fscache_t *fscp, cnode_t *pcp, char *nm, cnode_t *cp,
 297     cred_t *cr);
 298 off_t cachefs_dlog_rename(fscache_t *fscp, cnode_t *odcp, char *onm,
 299     cnode_t *ndcp, char *nnm, cred_t *cr, cnode_t *cp, cnode_t *delcp);
 300 off_t cachefs_dlog_mkdir(fscache_t *fscp, cnode_t *pcp, cnode_t *cp, char *nm,
 301     vattr_t *vap, cred_t *cr);
 302 off_t cachefs_dlog_rmdir(fscache_t *fscp, cnode_t *pcp, char *nm, cnode_t *cp,
 303     cred_t *cr);
 304 off_t cachefs_dlog_symlink(fscache_t *fscp, cnode_t *pcp, cnode_t *cp,
 305     char *lnm, vattr_t *vap, char *tnm, cred_t *cr);
 306 off_t cachefs_dlog_modify(fscache_t *fscp, cnode_t *cp, cred_t *cr,
 307     uint_t *seqp);
 308 int cachefs_dlog_mapfid(fscache_t *fscp, cnode_t *cp);
 309 uint_t cachefs_dlog_seqnext(fscache_t *fscp);
 310 #endif
 311 
 312 #ifdef __cplusplus
 313 }
 314 #endif
 315 
 316 #endif  /* _SYS_FS_CACHEFS_DLOG_H */