2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
11 * IRIX inode operations
22 * afs_syscall_icreatename64
35 * afs_syscall_ilistinode64
39 #include <afsconfig.h>
40 #include "afs/param.h"
43 #include "afs/sysincludes.h" /* Standard vendor system headers */
44 #include "afsincludes.h" /* Afs-based standard headers */
45 #include "afs/osi_inode.h"
46 #include "afs/afs_stats.h" /* statistics stuff */
48 #define BAD_IGET -1000
51 * SGI dependent system calls
55 * `INODESPECIAL' type inodes are ones that describe volumes.
57 #define INODESPECIAL 0xffffffff /* ... from ../vol/viceinode.h */
61 afsidestroy(struct inode *ip)
64 kmem_free(ip->i_afs, sizeof(struct afsparms));
69 extern int xfs_fstype;
72 getinode(struct vfs *vfsp, dev_t dev, ino_t inode, struct inode **ipp)
78 igetinode(struct vfs *vfsp, dev_t dev, ino_t inode, struct inode **ipp)
86 #define SET_XFS_ERROR(POS, DEV, INO) \
87 XFS_IGET_EPOS = (POS), XFS_IGET_DEV = (DEV), XFS_IGET_INO = (INO)
90 xfs_getinode(struct vfs *vfsp, dev_t dev, ino_t inode, struct xfs_inode **ipp)
96 vfsp = vfs_devsearch(dev, xfs_fstype);
98 SET_XFS_ERROR(1, dev, inode);
103 if (error = xfs_iget((((struct mount *)
104 ((vfsp)->vfs_bh.bh_first)->bd_pdata)), (void *)0,
105 (xfs_ino_t) inode, XFS_ILOCK_SHARED, &ip,
107 SET_XFS_ERROR(3, vfsp->vfs_dev, inode);
115 /* xfs_igetinode now returns an unlocked inode. This is fine, since we
116 * have a refcount on the holding vnode.
119 xfs_igetinode(struct vfs *vfsp, dev_t dev, ino_t inode,
120 struct xfs_inode **ipp)
122 struct xfs_inode *ip;
127 AFS_STATCNT(igetinode);
130 if (error = xfs_getinode(vfsp, dev, inode, &ip)) {
134 xfs_iunlock(ip, XFS_ILOCK_SHARED);
136 vattr.va_mask = AT_STAT;
137 AFS_VOP_GETATTR(vp, &vattr, 0, OSI_GET_CURRENT_CRED(), error);
139 SET_XFS_ERROR(4, vp->v_vfsp->vfs_dev, inode);
143 if (vattr.va_nlink == 0 || vattr.va_type != VREG) {
144 SET_XFS_ERROR(5, vp->v_vfsp->vfs_dev, inode);
153 /**************************************************************************
154 * inode creation routines.
156 ***************************************************************************/
167 icreate(struct icreateargs *uap, rval_t * rvp)
173 afs_syscall_icreate(dev, near_inode, param1, param2, param3, param4, rvp)
174 afs_uint32 dev, near_inode, param1, param2, param3, param4;
180 /* inode creation routines for icreatename64 entry point.
181 * Create a name in the namespace as well as the inode.
184 #include <afs/xfsattrs.h>
185 #include <sys/attributes.h>
187 extern char *int_to_base64(char *, int);
189 /* Lock against races creating/removing directory - vos zap RO, vos create RW*/
190 kmutex_t afs_vol_create_lock;
191 int afs_vol_create_lock_inited = 0;
192 #define AFS_LOCK_VOL_CREATE() { \
193 if (!afs_vol_create_lock_inited) { \
194 mutex_init(&afs_vol_create_lock, MUTEX_DEFAULT, \
195 "afs_vol_create_lock"); \
196 afs_vol_create_lock_inited = 1; \
198 mutex_enter(&afs_vol_create_lock); \
200 #define AFS_UNLOCK_VOL_CREATE() mutex_exit(&afs_vol_create_lock)
204 * Create an AFS inode in the XFS name space. If required create the proper
205 * containing directory. See sys/xfsattrs.h for the details on the naming
206 * conventions and the usage of file and directory attributes.
208 * The inode parameters are stored in an XFS attribute called "AFS". In
209 * addition gid is set to XFS_VICEMAGIC and uid is set to the low 31 bits
210 * of the RW volume id. This is so inode verification in iinc and idec
211 * don't need to get the attribute. Note that only the low 31 bits are set.
212 * This is because chmod only accepts up to MAX_UID and chmod is used
213 * to correct these values in xfs_ListViceInodes.
216 xfs_icreatename64(struct vfs *vfsp, int datap, int datalen,
217 afs_inode_params_t params, ino_t * inop)
219 #define AFS_PNAME_SIZE 16
222 b64_string_t stmp1, stmp2;
223 afs_xfs_attr_t attrs;
225 int name_version = AFS_XFS_NAME_VERS;
226 int code = 0, unused;
229 int rw_vno; /* volume ID of parent volume */
236 /* Get vnode for directory which will contain new inode. */
237 if (datalen >= AFS_PNAME_SIZE)
240 AFS_COPYINSTR((char *)datap, path, AFS_PNAME_SIZE - 1, &junk, unused);
245 rw_vno = (params[1] == INODESPECIAL) ? params[3] : params[0];
249 strcat(path, AFS_INODE_DIR_NAME);
250 strcat(path, int_to_base64(stmp1, rw_vno));
252 if (params[1] == INODESPECIAL)
253 AFS_LOCK_VOL_CREATE();
255 code = gop_lookupname(path, AFS_UIOSYS, FOLLOW, &dvp);
256 if (code == ENOENT) {
257 /* Maybe it's an old directory name format. */
258 AFS_COPYINSTR((char *)datap, name, AFS_PNAME_SIZE - 1, &junk, unused);
260 strcat(name, int_to_base64(stmp1, rw_vno));
261 code = gop_lookupname(name, AFS_UIOSYS, FOLLOW, &dvp);
263 /* Use old name format. */
265 name_version = AFS_XFS_NAME_VERS1;
269 if (code == ENOENT) {
270 afs_xfs_dattr_t dattr;
271 /* make directory. */
274 AFS_VN_OPEN(path, UIO_SYSSPACE, FCREAT | FEXCL, 0700, &dvp,
277 if (code == EEXIST) {
278 /* someone beat us to it? */
279 code = gop_lookupname(path, AFS_UIOSYS, NO_FOLLOW, &dvp);
282 AFS_UNLOCK_VOL_CREATE();
287 memset(&dattr, 0, sizeof(dattr));
288 dattr.atd_version = AFS_XFS_ATD_VERS;
289 dattr.atd_volume = rw_vno;
290 AFS_VOP_ATTR_SET(dvp, AFS_XFS_DATTR, (char *)&dattr,
291 SIZEOF_XFS_DATTR_T, ATTR_ROOT | ATTR_CREATE,
292 OSI_GET_CURRENT_CRED(), code);
296 (void)vn_remove(path, UIO_SYSSPACE, RMDIRECTORY);
297 AFS_UNLOCK_VOL_CREATE();
302 vattr.va_mask = AT_FSID | AT_NODEID; /* gets a guick return using FSID */
303 AFS_VOP_GETATTR(dvp, &vattr, 0, OSI_GET_CURRENT_CRED(), code);
309 memset(&attrs, 0, sizeof(attrs));
310 attrs.at_pino = vattr.va_nodeid;
313 /* Create the desired file. Use up to ten tries to create a unique name. */
314 (void)strcpy(name, path);
315 (void)strcat(name, "/.");
316 (void)strcat(name, int_to_base64(stmp2, params[2]));
317 s = &name[strlen(name)];
319 attrs.at_tag = 0; /* Initial guess at a unique tag. */
320 for (i = 0; i < 10; i++) {
323 strcat(s, int_to_base64(stmp1, attrs.at_tag));
325 AFS_VN_OPEN(name, UIO_SYSSPACE, FCREAT | FEXCL, 0600, &vp,
327 if (!code || code != EEXIST)
332 /* Unlock the creation process since the directory now has a file in it. */
333 if (params[1] == INODESPECIAL)
334 AFS_UNLOCK_VOL_CREATE();
337 /* Set attributes. */
338 memcpy((char *)attrs.at_param, (char *)params,
339 sizeof(afs_inode_params_t));
340 attrs.at_attr_version = AFS_XFS_ATTR_VERS;
341 attrs.at_name_version = name_version;
342 AFS_VOP_ATTR_SET(vp, AFS_XFS_ATTR, (char *)&attrs, SIZEOF_XFS_ATTR_T,
343 ATTR_ROOT | ATTR_CREATE, OSI_GET_CURRENT_CRED(),
347 vattr.va_uid = AFS_XFS_VNO_CLIP(params[0]);
348 vattr.va_gid = XFS_VICEMAGIC;
349 vattr.va_mask = AT_MODE | AT_UID | AT_GID;
350 AFS_VOP_SETATTR(vp, &vattr, 0, OSI_GET_CURRENT_CRED(), code);
353 vattr.va_mask = AT_NODEID;
354 AFS_VOP_GETATTR(vp, &vattr, 0, OSI_GET_CURRENT_CRED(), code);
357 *inop = vattr.va_nodeid;
362 /* remove partially created file. */
363 (void)vn_remove(name, UIO_SYSSPACE, RMFILE);
365 /* and directory if volume special file. */
367 AFS_LOCK_VOL_CREATE();
368 (void)vn_remove(path, UIO_SYSSPACE, RMDIRECTORY);
369 AFS_UNLOCK_VOL_CREATE();
375 /* afs_syscall_icreatename64
376 * This is the icreatename64 entry point used by the XFS
380 afs_syscall_icreatename64(int dev, int datap, int datalen, int paramp,
384 afs_inode_params_t param;
390 if (!afs_suser(NULL))
393 vfsp = vfs_devsearch(dev, VFS_FSTYPE_ANY);
398 AFS_COPYIN((char *)paramp, (char *)param, sizeof(afs_inode_params_t),
400 if (vfsp->vfs_fstype == xfs_fstype) {
401 code = xfs_icreatename64(vfsp, datap, datalen, param, &ino);
405 AFS_COPYOUT((char *)&ino, (char *)inop, sizeof(ino_t), code);
413 * iopen system calls -- open an inode for reading/writing
414 * Restricted to super user.
431 afs_syscall_iopen(int dev, ino_t inode, int usrmod, rval_t * rvp)
439 AFS_STATCNT(afs_syscall_iopen);
440 if (!afs_suser(NULL))
442 vfsp = vfs_devsearch(dev, xfs_fstype);
446 if (vfsp->vfs_fstype == xfs_fstype) {
447 struct xfs_inode *xip;
448 if (error = xfs_igetinode(vfsp, (dev_t) dev, inode, &xip))
451 if (error = vfile_alloc((usrmod + 1) & (FMASK), &fp, &fd)) {
456 osi_Panic("afs_syscall_iopen: bad fstype = %d\n", vfsp->vfs_fstype);
464 iopen(struct iopenargs *uap, rval_t * rvp)
467 return (afs_syscall_iopen
468 (uap->dev, (ino_t) uap->inode, uap->usrmod, rvp));
472 iopen64(struct iopenargs64 *uap, rval_t * rvp)
475 return (afs_syscall_iopen
476 (uap->dev, (ino_t) ((uap->inode_hi << 32) | uap->inode_lo),
481 * Support for iinc() and idec() system calls--increment or decrement
483 * Restricted to super user.
484 * Only VICEMAGIC type inodes.
489 * XFS iinc/idec code. Uses 64 bit inode numbers.
492 xfs_iincdec64(struct vfs *vfsp, ino_t inode, int inode_p1, int amount)
497 afs_xfs_attr_t attrs;
498 int length = SIZEOF_XFS_ATTR_T;
499 afs_xfs_dattr_t dattr;
505 xfs_iget((((struct mount *)((vfsp)->vfs_bh.bh_first)->bd_pdata)),
506 (void *)0, (xfs_ino_t) inode, XFS_ILOCK_SHARED, &ip,
512 xfs_iunlock(ip, XFS_ILOCK_SHARED);
514 vattr.va_mask = AT_GID | AT_UID | AT_MODE;
515 AFS_VOP_GETATTR(vp, &vattr, 0, OSI_GET_CURRENT_CRED(), code);
519 if (!code && (vattr.va_gid != XFS_VICEMAGIC))
522 if (!code && (AFS_XFS_VNO_CLIP(inode_p1) != vattr.va_uid))
530 nlink = vattr.va_mode & AFS_XFS_MODE_LINK_MASK;
536 vattr.va_mode &= ~AFS_XFS_MODE_LINK_MASK;
537 vattr.va_mode |= nlink;
538 vattr.va_mask = AT_MODE;
539 AFS_VOP_SETATTR(vp, &vattr, 0, OSI_GET_CURRENT_CRED(), code);
544 b64_string_t stmp1, stmp2;
548 length = SIZEOF_XFS_ATTR_T;
549 AFS_VOP_ATTR_GET(vp, AFS_XFS_ATTR, (char *)&attrs, &length, ATTR_ROOT,
550 OSI_GET_CURRENT_CRED(), code);
553 if (length != SIZEOF_XFS_ATTR_T
554 || attrs.at_attr_version != AFS_XFS_ATTR_VERS)
557 /* Get the vnode for the directory this file is in. */
561 code = xfs_getinode(vp->v_vfsp, NULL, attrs.at_pino, &ip);
566 xfs_iunlock(ip, XFS_ILOCK_SHARED);
568 /* Verify directory attributes. */
569 length = SIZEOF_XFS_DATTR_T;
570 AFS_VOP_ATTR_GET(dvp, AFS_XFS_DATTR, (char *)&dattr, &length,
571 ATTR_ROOT, OSI_GET_CURRENT_CRED(), code);
573 if (length != SIZEOF_XFS_DATTR_T
574 || dattr.atd_version != AFS_XFS_ATD_VERS)
583 strcat(path, int_to_base64(stmp1, attrs.at_param[2]));
585 strcat(path, int_to_base64(stmp1, attrs.at_tag));
587 AFS_VOP_REMOVE(dvp, path, OSI_GET_CURRENT_CRED(), code);
591 vattr.va_mask = AT_NLINK;
592 AFS_VOP_GETATTR(dvp, &vattr, 0, OSI_GET_CURRENT_CRED(), code2);
594 if (vattr.va_nlink == 2) {
595 vnode_t *ddvp; /* parent of volume directory. */
596 /* Try to remove the directory if this is a volume
597 * special file. It's ok to fail.
599 AFS_VOP_LOOKUP(dvp, "..", &ddvp, NULL,
600 0, OSI_GET_CURRENT_RDIR(),
601 OSI_GET_CURRENT_CRED(), code2);
606 if (attrs.at_name_version == AFS_XFS_NAME_VERS2)
607 strcpy(path, AFS_INODE_DIR_NAME);
611 (attrs.at_param[1] ==
612 INODESPECIAL) ? attrs.
613 at_param[3] : attrs.at_param[0]);
615 AFS_LOCK_VOL_CREATE();
616 AFS_VOP_RMDIR(ddvp, path, OSI_GET_CURRENT_CDIR(),
617 OSI_GET_CURRENT_CRED(), code2);
618 AFS_UNLOCK_VOL_CREATE();
631 iincdec64(int dev, int inode_hi, int inode_lo, int inode_p1, int amount)
635 if (!afs_suser(NULL))
637 vfsp = vfs_devsearch(dev, VFS_FSTYPE_ANY);
642 if (vfsp->vfs_fstype == xfs_fstype) {
647 return xfs_iincdec64(vfsp, inode, inode_p1, amount);
653 afs_syscall_idec64(int dev, int inode_hi, int inode_lo, int inode_p1)
655 return iincdec64(dev, inode_hi, inode_lo, inode_p1, -1);
659 afs_syscall_iinc64(int dev, int inode_hi, int inode_lo, int inode_p1)
661 return iincdec64(dev, inode_hi, inode_lo, inode_p1, 1);
671 iinc(struct iincargs *uap, rval_t * rvp)
678 idec(struct iincargs *uap, rval_t * rvp)
684 /* afs_syscall_ilistinode64
685 * Gathers up all required info for ListViceInodes in one system call.
688 afs_syscall_ilistinode64(int dev, int inode_hi, int inode_lo, int datap,
697 afs_xfs_attr_t attrs;
702 if (!afs_suser(NULL))
704 vfsp = vfs_devsearch(dev, xfs_fstype);
709 AFS_COPYIN((char *)datalenp, &idatalen, sizeof(int), code);
710 if (idatalen < sizeof(i_list_inode_t)) {
711 idatalen = sizeof(i_list_inode_t);
712 AFS_COPYOUT((char *)datalenp, (char *)&idatalen, sizeof(int), code);
715 idatalen = sizeof(i_list_inode_t);
716 AFS_COPYOUT((char *)datalenp, (char *)&idatalen, sizeof(int), code);
718 AFS_COPYIN((char *)datap, (char *)&data, sizeof(i_list_inode_t), code);
719 if (data.ili_version != AFS_XFS_ILI_VERSION) {
720 data.ili_version = AFS_XFS_ILI_VERSION;
721 AFS_COPYOUT((char *)&data, (char *)datap, sizeof(i_list_inode_t),
731 xfs_iget((((struct mount *)((vfsp)->vfs_bh.bh_first)->bd_pdata)),
732 (void *)0, (xfs_ino_t) inode, XFS_ILOCK_SHARED, &ip,
738 xfs_iunlock(ip, XFS_ILOCK_SHARED);
740 length = SIZEOF_XFS_ATTR_T;
742 AFS_VOP_ATTR_GET(vp, AFS_XFS_ATTR, (char *)&attrs, &length, ATTR_ROOT,
743 OSI_GET_CURRENT_CRED(), code);
749 if (attrs.at_attr_version != AFS_XFS_ATTR_VERS)
754 vattr.va_mask = AT_STAT;
755 AFS_VOP_GETATTR(vp, &vattr, 0, OSI_GET_CURRENT_CRED(), code);
759 memset(&data, 0, sizeof(data));
760 data.ili_info.inodeNumber = inode;
761 data.ili_info.byteCount = vattr.va_size;
762 data.ili_info.linkCount = (vattr.va_mode & AFS_XFS_MODE_LINK_MASK);
763 memcpy((char *)data.ili_info.param, (char *)attrs.at_param,
764 sizeof(data.ili_info.param));
765 data.ili_attr_version = attrs.at_attr_version;
766 data.ili_name_version = attrs.at_name_version;
767 data.ili_tag = attrs.at_tag;
768 data.ili_pino = attrs.at_pino;
769 data.ili_vno = vattr.va_uid;
770 data.ili_magic = vattr.va_gid;
771 AFS_COPYOUT((char *)&data, (char *)datap, sizeof(data), code);