static noinline_for_stack int cpup_iattr(struct dentry *dst, aufs_bindex_t bindex, struct dentry *h_src) { int err, sbits; struct iattr ia; struct path h_path; struct inode *h_isrc; h_path.dentry = au_h_dptr(dst, bindex); h_path.mnt = au_sbr_mnt(dst->d_sb, bindex); h_isrc = h_src->d_inode; ia.ia_valid = ATTR_FORCE | ATTR_MODE | ATTR_UID | ATTR_GID | ATTR_ATIME | ATTR_MTIME | ATTR_ATIME_SET | ATTR_MTIME_SET; ia.ia_mode = h_isrc->i_mode; ia.ia_uid = h_isrc->i_uid; ia.ia_gid = h_isrc->i_gid; ia.ia_atime = h_isrc->i_atime; ia.ia_mtime = h_isrc->i_mtime; sbits = !!(ia.ia_mode & (S_ISUID | S_ISGID)); au_cpup_attr_flags(h_path.dentry->d_inode, h_isrc); err = vfsub_notify_change(&h_path, &ia); /* is this nfs only? */ if (!err && sbits && au_test_nfs(h_path.dentry->d_sb)) { ia.ia_valid = ATTR_FORCE | ATTR_MODE; ia.ia_mode = h_isrc->i_mode; err = vfsub_notify_change(&h_path, &ia); } return err; }
static noinline_for_stack int cpup_iattr(struct dentry *dst, aufs_bindex_t bindex, struct dentry *h_src, struct au_cpup_reg_attr *h_src_attr) { int err, sbits; struct iattr ia; struct path h_path; struct inode *h_isrc, *h_idst; struct kstat *h_st; h_path.dentry = au_h_dptr(dst, bindex); h_idst = h_path.dentry->d_inode; h_path.mnt = au_sbr_mnt(dst->d_sb, bindex); h_isrc = h_src->d_inode; ia.ia_valid = ATTR_FORCE | ATTR_UID | ATTR_GID | ATTR_ATIME | ATTR_MTIME | ATTR_ATIME_SET | ATTR_MTIME_SET; if (h_src_attr && h_src_attr->valid) { h_st = &h_src_attr->st; ia.ia_uid = h_st->uid; ia.ia_gid = h_st->gid; ia.ia_atime = h_st->atime; ia.ia_mtime = h_st->mtime; if (h_idst->i_mode != h_st->mode && !S_ISLNK(h_idst->i_mode)) { ia.ia_valid |= ATTR_MODE; ia.ia_mode = h_st->mode; } sbits = !!(h_st->mode & (S_ISUID | S_ISGID)); au_cpup_attr_flags(h_idst, h_src_attr->iflags); } else { ia.ia_uid = h_isrc->i_uid; ia.ia_gid = h_isrc->i_gid; ia.ia_atime = h_isrc->i_atime; ia.ia_mtime = h_isrc->i_mtime; if (h_idst->i_mode != h_isrc->i_mode && !S_ISLNK(h_idst->i_mode)) { ia.ia_valid |= ATTR_MODE; ia.ia_mode = h_isrc->i_mode; } sbits = !!(h_isrc->i_mode & (S_ISUID | S_ISGID)); au_cpup_attr_flags(h_idst, h_isrc->i_flags); } err = vfsub_notify_change(&h_path, &ia); /* is this nfs only? */ if (!err && sbits && au_test_nfs(h_path.dentry->d_sb)) { ia.ia_valid = ATTR_FORCE | ATTR_MODE; ia.ia_mode = h_isrc->i_mode; err = vfsub_notify_change(&h_path, &ia); } return err; }
void au_dtime_revert(struct au_dtime *dt) { struct iattr attr; int err; struct au_hin_ignore ign[2]; struct vfsub_args vargs; LKTRTrace("%.*s\n", AuDLNPair(dt->dt_dentry)); attr.ia_atime = dt->dt_atime; attr.ia_mtime = dt->dt_mtime; attr.ia_valid = ATTR_FORCE | ATTR_MTIME | ATTR_MTIME_SET | ATTR_ATIME | ATTR_ATIME_SET; vfsub_args_init(&vargs, ign, au_test_dlgt(au_mntflags(dt->dt_dentry->d_sb)), 0); /* * IN_ATTRIB should be divided into * IN_ATTRIB_ATIME, IN_ATTRIB_MTIME ..., * and define all ORed new IN_ATTRIB macro. */ vfsub_ign_hinode(&vargs, IN_ATTRIB, dt->dt_hinode); vfsub_ign_hinode(&vargs, IN_ATTRIB, dt->dt_hdir); err = vfsub_notify_change(dt->dt_h_dentry, &attr, &vargs); if (unlikely(err)) AuWarn("restoring timestamps failed(%d). ignored\n", err); }
static noinline_for_stack int cpup_iattr(struct dentry *dst, aufs_bindex_t bindex, struct dentry *h_src, struct au_hinode *hdir, struct vfsub_args *vargs) { int err, sbits; struct dentry *h_dst; struct iattr ia; struct inode *h_isrc, *h_idst; h_dst = au_h_dptr(dst, bindex); LKTRTrace("%.*s\n", AuDLNPair(h_dst)); h_idst = h_dst->d_inode; /* todo? IMustLock(h_idst); */ h_isrc = h_src->d_inode; /* todo? IMustLock(h_isrc); */ ia.ia_valid = ATTR_FORCE | ATTR_MODE | ATTR_UID | ATTR_GID | ATTR_ATIME | ATTR_MTIME | ATTR_ATIME_SET | ATTR_MTIME_SET; ia.ia_mode = h_isrc->i_mode; ia.ia_uid = h_isrc->i_uid; ia.ia_gid = h_isrc->i_gid; ia.ia_atime = h_isrc->i_atime; ia.ia_mtime = h_isrc->i_mtime; sbits = !!(ia.ia_mode & (S_ISUID | S_ISGID)); au_cpup_attr_flags(h_idst, h_isrc); vfsub_args_reinit(vargs); vfsub_ign_hinode(vargs, IN_ATTRIB, hdir); err = vfsub_notify_change(h_dst, &ia, vargs); /* is this nfs only? */ if (!err && sbits && au_test_nfs(h_dst->d_sb)) { ia.ia_valid = ATTR_FORCE | ATTR_MODE; ia.ia_mode = h_isrc->i_mode; vfsub_args_reinit(vargs); vfsub_ign_hinode(vargs, IN_ATTRIB, hdir); err = vfsub_notify_change(h_dst, &ia, vargs); } AuTraceErr(err); return err; }
void au_dtime_revert(struct au_dtime *dt) { struct iattr attr; int err; attr.ia_atime = dt->dt_atime; attr.ia_mtime = dt->dt_mtime; attr.ia_valid = ATTR_FORCE | ATTR_MTIME | ATTR_MTIME_SET | ATTR_ATIME | ATTR_ATIME_SET; err = vfsub_notify_change(&dt->dt_h_path, &attr); if (unlikely(err)) pr_warn("restoring timestamps failed(%d). ignored\n", err); }
void au_dtime_revert(struct au_dtime *dt) { struct iattr attr; int err; attr.ia_atime = dt->dt_atime; attr.ia_mtime = dt->dt_mtime; attr.ia_valid = ATTR_FORCE | ATTR_MTIME | ATTR_MTIME_SET | ATTR_ATIME | ATTR_ATIME_SET; /* no delegation since this is a directory */ err = vfsub_notify_change(&dt->dt_h_path, &attr, /*delegated*/NULL); if (unlikely(err)) pr_warn("restoring timestamps failed(%d). ignored\n", err); }
static int au_do_copy_file(struct file *dst, struct file *src, loff_t len, char *buf, unsigned long blksize) { int err; size_t sz, rbytes, wbytes; unsigned char all_zero; char *p, *zp; struct mutex *h_mtx; /* reduce stack usage */ struct iattr *ia; zp = page_address(ZERO_PAGE(0)); if (unlikely(!zp)) return -ENOMEM; /* possible? */ err = 0; all_zero = 0; while (len) { AuDbg("len %lld\n", len); sz = blksize; if (len < blksize) sz = len; rbytes = 0; /* todo: signal_pending? */ while (!rbytes || err == -EAGAIN || err == -EINTR) { rbytes = vfsub_read_k(src, buf, sz, &src->f_pos); err = rbytes; } if (unlikely(err < 0)) break; all_zero = 0; if (len >= rbytes && rbytes == blksize) all_zero = !memcmp(buf, zp, rbytes); if (!all_zero) { wbytes = rbytes; p = buf; while (wbytes) { size_t b; b = vfsub_write_k(dst, p, wbytes, &dst->f_pos); err = b; /* todo: signal_pending? */ if (unlikely(err == -EAGAIN || err == -EINTR)) continue; if (unlikely(err < 0)) break; wbytes -= b; p += b; } } else { loff_t res; AuLabel(hole); res = vfsub_llseek(dst, rbytes, SEEK_CUR); err = res; if (unlikely(res < 0)) break; } len -= rbytes; err = 0; } /* the last block may be a hole */ if (!err && all_zero) { AuLabel(last hole); err = 1; if (au_test_nfs(dst->f_dentry->d_sb)) { /* nfs requires this step to make last hole */ /* is this only nfs? */ do { /* todo: signal_pending? */ err = vfsub_write_k(dst, "\0", 1, &dst->f_pos); } while (err == -EAGAIN || err == -EINTR); if (err == 1) dst->f_pos--; } if (err == 1) { ia = (void *)buf; ia->ia_size = dst->f_pos; ia->ia_valid = ATTR_SIZE | ATTR_FILE; ia->ia_file = dst; h_mtx = &dst->f_dentry->d_inode->i_mutex; mutex_lock_nested(h_mtx, AuLsc_I_CHILD2); err = vfsub_notify_change(&dst->f_path, ia); mutex_unlock(h_mtx); } } return err; }
static noinline_for_stack int cpup_iattr(struct dentry *dst, aufs_bindex_t bindex, struct dentry *h_src, struct au_cpup_reg_attr *h_src_attr) { int err, sbits, icex; unsigned int mnt_flags; unsigned char verbose; struct iattr ia; struct path h_path; struct inode *h_isrc, *h_idst; struct kstat *h_st; struct au_branch *br; h_path.dentry = au_h_dptr(dst, bindex); h_idst = d_inode(h_path.dentry); br = au_sbr(dst->d_sb, bindex); h_path.mnt = au_br_mnt(br); h_isrc = d_inode(h_src); ia.ia_valid = ATTR_FORCE | ATTR_UID | ATTR_GID | ATTR_ATIME | ATTR_MTIME | ATTR_ATIME_SET | ATTR_MTIME_SET; if (h_src_attr && h_src_attr->valid) { h_st = &h_src_attr->st; ia.ia_uid = h_st->uid; ia.ia_gid = h_st->gid; ia.ia_atime = h_st->atime; ia.ia_mtime = h_st->mtime; if (h_idst->i_mode != h_st->mode && !S_ISLNK(h_idst->i_mode)) { ia.ia_valid |= ATTR_MODE; ia.ia_mode = h_st->mode; } sbits = !!(h_st->mode & (S_ISUID | S_ISGID)); au_cpup_attr_flags(h_idst, h_src_attr->iflags); } else { ia.ia_uid = h_isrc->i_uid; ia.ia_gid = h_isrc->i_gid; ia.ia_atime = h_isrc->i_atime; ia.ia_mtime = h_isrc->i_mtime; if (h_idst->i_mode != h_isrc->i_mode && !S_ISLNK(h_idst->i_mode)) { ia.ia_valid |= ATTR_MODE; ia.ia_mode = h_isrc->i_mode; } sbits = !!(h_isrc->i_mode & (S_ISUID | S_ISGID)); au_cpup_attr_flags(h_idst, h_isrc->i_flags); } /* no delegation since it is just created */ err = vfsub_notify_change(&h_path, &ia, /*delegated*/NULL); /* is this nfs only? */ if (!err && sbits && au_test_nfs(h_path.dentry->d_sb)) { ia.ia_valid = ATTR_FORCE | ATTR_MODE; ia.ia_mode = h_isrc->i_mode; err = vfsub_notify_change(&h_path, &ia, /*delegated*/NULL); } icex = br->br_perm & AuBrAttr_ICEX; if (!err) { mnt_flags = au_mntflags(dst->d_sb); verbose = !!au_opt_test(mnt_flags, VERBOSE); err = au_cpup_xattr(h_path.dentry, h_src, icex, verbose); } return err; }