1*e9be9d5eSMiklos Szeredi /* 2*e9be9d5eSMiklos Szeredi * 3*e9be9d5eSMiklos Szeredi * Copyright (C) 2011 Novell Inc. 4*e9be9d5eSMiklos Szeredi * 5*e9be9d5eSMiklos Szeredi * This program is free software; you can redistribute it and/or modify it 6*e9be9d5eSMiklos Szeredi * under the terms of the GNU General Public License version 2 as published by 7*e9be9d5eSMiklos Szeredi * the Free Software Foundation. 8*e9be9d5eSMiklos Szeredi */ 9*e9be9d5eSMiklos Szeredi 10*e9be9d5eSMiklos Szeredi #include <linux/fs.h> 11*e9be9d5eSMiklos Szeredi #include <linux/slab.h> 12*e9be9d5eSMiklos Szeredi #include <linux/xattr.h> 13*e9be9d5eSMiklos Szeredi #include "overlayfs.h" 14*e9be9d5eSMiklos Szeredi 15*e9be9d5eSMiklos Szeredi static int ovl_copy_up_last(struct dentry *dentry, struct iattr *attr, 16*e9be9d5eSMiklos Szeredi bool no_data) 17*e9be9d5eSMiklos Szeredi { 18*e9be9d5eSMiklos Szeredi int err; 19*e9be9d5eSMiklos Szeredi struct dentry *parent; 20*e9be9d5eSMiklos Szeredi struct kstat stat; 21*e9be9d5eSMiklos Szeredi struct path lowerpath; 22*e9be9d5eSMiklos Szeredi 23*e9be9d5eSMiklos Szeredi parent = dget_parent(dentry); 24*e9be9d5eSMiklos Szeredi err = ovl_copy_up(parent); 25*e9be9d5eSMiklos Szeredi if (err) 26*e9be9d5eSMiklos Szeredi goto out_dput_parent; 27*e9be9d5eSMiklos Szeredi 28*e9be9d5eSMiklos Szeredi ovl_path_lower(dentry, &lowerpath); 29*e9be9d5eSMiklos Szeredi err = vfs_getattr(&lowerpath, &stat); 30*e9be9d5eSMiklos Szeredi if (err) 31*e9be9d5eSMiklos Szeredi goto out_dput_parent; 32*e9be9d5eSMiklos Szeredi 33*e9be9d5eSMiklos Szeredi if (no_data) 34*e9be9d5eSMiklos Szeredi stat.size = 0; 35*e9be9d5eSMiklos Szeredi 36*e9be9d5eSMiklos Szeredi err = ovl_copy_up_one(parent, dentry, &lowerpath, &stat, attr); 37*e9be9d5eSMiklos Szeredi 38*e9be9d5eSMiklos Szeredi out_dput_parent: 39*e9be9d5eSMiklos Szeredi dput(parent); 40*e9be9d5eSMiklos Szeredi return err; 41*e9be9d5eSMiklos Szeredi } 42*e9be9d5eSMiklos Szeredi 43*e9be9d5eSMiklos Szeredi int ovl_setattr(struct dentry *dentry, struct iattr *attr) 44*e9be9d5eSMiklos Szeredi { 45*e9be9d5eSMiklos Szeredi int err; 46*e9be9d5eSMiklos Szeredi struct dentry *upperdentry; 47*e9be9d5eSMiklos Szeredi 48*e9be9d5eSMiklos Szeredi err = ovl_want_write(dentry); 49*e9be9d5eSMiklos Szeredi if (err) 50*e9be9d5eSMiklos Szeredi goto out; 51*e9be9d5eSMiklos Szeredi 52*e9be9d5eSMiklos Szeredi upperdentry = ovl_dentry_upper(dentry); 53*e9be9d5eSMiklos Szeredi if (upperdentry) { 54*e9be9d5eSMiklos Szeredi mutex_lock(&upperdentry->d_inode->i_mutex); 55*e9be9d5eSMiklos Szeredi err = notify_change(upperdentry, attr, NULL); 56*e9be9d5eSMiklos Szeredi mutex_unlock(&upperdentry->d_inode->i_mutex); 57*e9be9d5eSMiklos Szeredi } else { 58*e9be9d5eSMiklos Szeredi err = ovl_copy_up_last(dentry, attr, false); 59*e9be9d5eSMiklos Szeredi } 60*e9be9d5eSMiklos Szeredi ovl_drop_write(dentry); 61*e9be9d5eSMiklos Szeredi out: 62*e9be9d5eSMiklos Szeredi return err; 63*e9be9d5eSMiklos Szeredi } 64*e9be9d5eSMiklos Szeredi 65*e9be9d5eSMiklos Szeredi static int ovl_getattr(struct vfsmount *mnt, struct dentry *dentry, 66*e9be9d5eSMiklos Szeredi struct kstat *stat) 67*e9be9d5eSMiklos Szeredi { 68*e9be9d5eSMiklos Szeredi struct path realpath; 69*e9be9d5eSMiklos Szeredi 70*e9be9d5eSMiklos Szeredi ovl_path_real(dentry, &realpath); 71*e9be9d5eSMiklos Szeredi return vfs_getattr(&realpath, stat); 72*e9be9d5eSMiklos Szeredi } 73*e9be9d5eSMiklos Szeredi 74*e9be9d5eSMiklos Szeredi int ovl_permission(struct inode *inode, int mask) 75*e9be9d5eSMiklos Szeredi { 76*e9be9d5eSMiklos Szeredi struct ovl_entry *oe; 77*e9be9d5eSMiklos Szeredi struct dentry *alias = NULL; 78*e9be9d5eSMiklos Szeredi struct inode *realinode; 79*e9be9d5eSMiklos Szeredi struct dentry *realdentry; 80*e9be9d5eSMiklos Szeredi bool is_upper; 81*e9be9d5eSMiklos Szeredi int err; 82*e9be9d5eSMiklos Szeredi 83*e9be9d5eSMiklos Szeredi if (S_ISDIR(inode->i_mode)) { 84*e9be9d5eSMiklos Szeredi oe = inode->i_private; 85*e9be9d5eSMiklos Szeredi } else if (mask & MAY_NOT_BLOCK) { 86*e9be9d5eSMiklos Szeredi return -ECHILD; 87*e9be9d5eSMiklos Szeredi } else { 88*e9be9d5eSMiklos Szeredi /* 89*e9be9d5eSMiklos Szeredi * For non-directories find an alias and get the info 90*e9be9d5eSMiklos Szeredi * from there. 91*e9be9d5eSMiklos Szeredi */ 92*e9be9d5eSMiklos Szeredi alias = d_find_any_alias(inode); 93*e9be9d5eSMiklos Szeredi if (WARN_ON(!alias)) 94*e9be9d5eSMiklos Szeredi return -ENOENT; 95*e9be9d5eSMiklos Szeredi 96*e9be9d5eSMiklos Szeredi oe = alias->d_fsdata; 97*e9be9d5eSMiklos Szeredi } 98*e9be9d5eSMiklos Szeredi 99*e9be9d5eSMiklos Szeredi realdentry = ovl_entry_real(oe, &is_upper); 100*e9be9d5eSMiklos Szeredi 101*e9be9d5eSMiklos Szeredi /* Careful in RCU walk mode */ 102*e9be9d5eSMiklos Szeredi realinode = ACCESS_ONCE(realdentry->d_inode); 103*e9be9d5eSMiklos Szeredi if (!realinode) { 104*e9be9d5eSMiklos Szeredi WARN_ON(!(mask & MAY_NOT_BLOCK)); 105*e9be9d5eSMiklos Szeredi err = -ENOENT; 106*e9be9d5eSMiklos Szeredi goto out_dput; 107*e9be9d5eSMiklos Szeredi } 108*e9be9d5eSMiklos Szeredi 109*e9be9d5eSMiklos Szeredi if (mask & MAY_WRITE) { 110*e9be9d5eSMiklos Szeredi umode_t mode = realinode->i_mode; 111*e9be9d5eSMiklos Szeredi 112*e9be9d5eSMiklos Szeredi /* 113*e9be9d5eSMiklos Szeredi * Writes will always be redirected to upper layer, so 114*e9be9d5eSMiklos Szeredi * ignore lower layer being read-only. 115*e9be9d5eSMiklos Szeredi * 116*e9be9d5eSMiklos Szeredi * If the overlay itself is read-only then proceed 117*e9be9d5eSMiklos Szeredi * with the permission check, don't return EROFS. 118*e9be9d5eSMiklos Szeredi * This will only happen if this is the lower layer of 119*e9be9d5eSMiklos Szeredi * another overlayfs. 120*e9be9d5eSMiklos Szeredi * 121*e9be9d5eSMiklos Szeredi * If upper fs becomes read-only after the overlay was 122*e9be9d5eSMiklos Szeredi * constructed return EROFS to prevent modification of 123*e9be9d5eSMiklos Szeredi * upper layer. 124*e9be9d5eSMiklos Szeredi */ 125*e9be9d5eSMiklos Szeredi err = -EROFS; 126*e9be9d5eSMiklos Szeredi if (is_upper && !IS_RDONLY(inode) && IS_RDONLY(realinode) && 127*e9be9d5eSMiklos Szeredi (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))) 128*e9be9d5eSMiklos Szeredi goto out_dput; 129*e9be9d5eSMiklos Szeredi } 130*e9be9d5eSMiklos Szeredi 131*e9be9d5eSMiklos Szeredi err = __inode_permission(realinode, mask); 132*e9be9d5eSMiklos Szeredi out_dput: 133*e9be9d5eSMiklos Szeredi dput(alias); 134*e9be9d5eSMiklos Szeredi return err; 135*e9be9d5eSMiklos Szeredi } 136*e9be9d5eSMiklos Szeredi 137*e9be9d5eSMiklos Szeredi 138*e9be9d5eSMiklos Szeredi struct ovl_link_data { 139*e9be9d5eSMiklos Szeredi struct dentry *realdentry; 140*e9be9d5eSMiklos Szeredi void *cookie; 141*e9be9d5eSMiklos Szeredi }; 142*e9be9d5eSMiklos Szeredi 143*e9be9d5eSMiklos Szeredi static void *ovl_follow_link(struct dentry *dentry, struct nameidata *nd) 144*e9be9d5eSMiklos Szeredi { 145*e9be9d5eSMiklos Szeredi void *ret; 146*e9be9d5eSMiklos Szeredi struct dentry *realdentry; 147*e9be9d5eSMiklos Szeredi struct inode *realinode; 148*e9be9d5eSMiklos Szeredi 149*e9be9d5eSMiklos Szeredi realdentry = ovl_dentry_real(dentry); 150*e9be9d5eSMiklos Szeredi realinode = realdentry->d_inode; 151*e9be9d5eSMiklos Szeredi 152*e9be9d5eSMiklos Szeredi if (WARN_ON(!realinode->i_op->follow_link)) 153*e9be9d5eSMiklos Szeredi return ERR_PTR(-EPERM); 154*e9be9d5eSMiklos Szeredi 155*e9be9d5eSMiklos Szeredi ret = realinode->i_op->follow_link(realdentry, nd); 156*e9be9d5eSMiklos Szeredi if (IS_ERR(ret)) 157*e9be9d5eSMiklos Szeredi return ret; 158*e9be9d5eSMiklos Szeredi 159*e9be9d5eSMiklos Szeredi if (realinode->i_op->put_link) { 160*e9be9d5eSMiklos Szeredi struct ovl_link_data *data; 161*e9be9d5eSMiklos Szeredi 162*e9be9d5eSMiklos Szeredi data = kmalloc(sizeof(struct ovl_link_data), GFP_KERNEL); 163*e9be9d5eSMiklos Szeredi if (!data) { 164*e9be9d5eSMiklos Szeredi realinode->i_op->put_link(realdentry, nd, ret); 165*e9be9d5eSMiklos Szeredi return ERR_PTR(-ENOMEM); 166*e9be9d5eSMiklos Szeredi } 167*e9be9d5eSMiklos Szeredi data->realdentry = realdentry; 168*e9be9d5eSMiklos Szeredi data->cookie = ret; 169*e9be9d5eSMiklos Szeredi 170*e9be9d5eSMiklos Szeredi return data; 171*e9be9d5eSMiklos Szeredi } else { 172*e9be9d5eSMiklos Szeredi return NULL; 173*e9be9d5eSMiklos Szeredi } 174*e9be9d5eSMiklos Szeredi } 175*e9be9d5eSMiklos Szeredi 176*e9be9d5eSMiklos Szeredi static void ovl_put_link(struct dentry *dentry, struct nameidata *nd, void *c) 177*e9be9d5eSMiklos Szeredi { 178*e9be9d5eSMiklos Szeredi struct inode *realinode; 179*e9be9d5eSMiklos Szeredi struct ovl_link_data *data = c; 180*e9be9d5eSMiklos Szeredi 181*e9be9d5eSMiklos Szeredi if (!data) 182*e9be9d5eSMiklos Szeredi return; 183*e9be9d5eSMiklos Szeredi 184*e9be9d5eSMiklos Szeredi realinode = data->realdentry->d_inode; 185*e9be9d5eSMiklos Szeredi realinode->i_op->put_link(data->realdentry, nd, data->cookie); 186*e9be9d5eSMiklos Szeredi kfree(data); 187*e9be9d5eSMiklos Szeredi } 188*e9be9d5eSMiklos Szeredi 189*e9be9d5eSMiklos Szeredi static int ovl_readlink(struct dentry *dentry, char __user *buf, int bufsiz) 190*e9be9d5eSMiklos Szeredi { 191*e9be9d5eSMiklos Szeredi struct path realpath; 192*e9be9d5eSMiklos Szeredi struct inode *realinode; 193*e9be9d5eSMiklos Szeredi 194*e9be9d5eSMiklos Szeredi ovl_path_real(dentry, &realpath); 195*e9be9d5eSMiklos Szeredi realinode = realpath.dentry->d_inode; 196*e9be9d5eSMiklos Szeredi 197*e9be9d5eSMiklos Szeredi if (!realinode->i_op->readlink) 198*e9be9d5eSMiklos Szeredi return -EINVAL; 199*e9be9d5eSMiklos Szeredi 200*e9be9d5eSMiklos Szeredi touch_atime(&realpath); 201*e9be9d5eSMiklos Szeredi 202*e9be9d5eSMiklos Szeredi return realinode->i_op->readlink(realpath.dentry, buf, bufsiz); 203*e9be9d5eSMiklos Szeredi } 204*e9be9d5eSMiklos Szeredi 205*e9be9d5eSMiklos Szeredi 206*e9be9d5eSMiklos Szeredi static bool ovl_is_private_xattr(const char *name) 207*e9be9d5eSMiklos Szeredi { 208*e9be9d5eSMiklos Szeredi return strncmp(name, "trusted.overlay.", 14) == 0; 209*e9be9d5eSMiklos Szeredi } 210*e9be9d5eSMiklos Szeredi 211*e9be9d5eSMiklos Szeredi int ovl_setxattr(struct dentry *dentry, const char *name, 212*e9be9d5eSMiklos Szeredi const void *value, size_t size, int flags) 213*e9be9d5eSMiklos Szeredi { 214*e9be9d5eSMiklos Szeredi int err; 215*e9be9d5eSMiklos Szeredi struct dentry *upperdentry; 216*e9be9d5eSMiklos Szeredi 217*e9be9d5eSMiklos Szeredi err = ovl_want_write(dentry); 218*e9be9d5eSMiklos Szeredi if (err) 219*e9be9d5eSMiklos Szeredi goto out; 220*e9be9d5eSMiklos Szeredi 221*e9be9d5eSMiklos Szeredi err = -EPERM; 222*e9be9d5eSMiklos Szeredi if (ovl_is_private_xattr(name)) 223*e9be9d5eSMiklos Szeredi goto out_drop_write; 224*e9be9d5eSMiklos Szeredi 225*e9be9d5eSMiklos Szeredi err = ovl_copy_up(dentry); 226*e9be9d5eSMiklos Szeredi if (err) 227*e9be9d5eSMiklos Szeredi goto out_drop_write; 228*e9be9d5eSMiklos Szeredi 229*e9be9d5eSMiklos Szeredi upperdentry = ovl_dentry_upper(dentry); 230*e9be9d5eSMiklos Szeredi err = vfs_setxattr(upperdentry, name, value, size, flags); 231*e9be9d5eSMiklos Szeredi 232*e9be9d5eSMiklos Szeredi out_drop_write: 233*e9be9d5eSMiklos Szeredi ovl_drop_write(dentry); 234*e9be9d5eSMiklos Szeredi out: 235*e9be9d5eSMiklos Szeredi return err; 236*e9be9d5eSMiklos Szeredi } 237*e9be9d5eSMiklos Szeredi 238*e9be9d5eSMiklos Szeredi ssize_t ovl_getxattr(struct dentry *dentry, const char *name, 239*e9be9d5eSMiklos Szeredi void *value, size_t size) 240*e9be9d5eSMiklos Szeredi { 241*e9be9d5eSMiklos Szeredi if (ovl_path_type(dentry->d_parent) == OVL_PATH_MERGE && 242*e9be9d5eSMiklos Szeredi ovl_is_private_xattr(name)) 243*e9be9d5eSMiklos Szeredi return -ENODATA; 244*e9be9d5eSMiklos Szeredi 245*e9be9d5eSMiklos Szeredi return vfs_getxattr(ovl_dentry_real(dentry), name, value, size); 246*e9be9d5eSMiklos Szeredi } 247*e9be9d5eSMiklos Szeredi 248*e9be9d5eSMiklos Szeredi ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size) 249*e9be9d5eSMiklos Szeredi { 250*e9be9d5eSMiklos Szeredi ssize_t res; 251*e9be9d5eSMiklos Szeredi int off; 252*e9be9d5eSMiklos Szeredi 253*e9be9d5eSMiklos Szeredi res = vfs_listxattr(ovl_dentry_real(dentry), list, size); 254*e9be9d5eSMiklos Szeredi if (res <= 0 || size == 0) 255*e9be9d5eSMiklos Szeredi return res; 256*e9be9d5eSMiklos Szeredi 257*e9be9d5eSMiklos Szeredi if (ovl_path_type(dentry->d_parent) != OVL_PATH_MERGE) 258*e9be9d5eSMiklos Szeredi return res; 259*e9be9d5eSMiklos Szeredi 260*e9be9d5eSMiklos Szeredi /* filter out private xattrs */ 261*e9be9d5eSMiklos Szeredi for (off = 0; off < res;) { 262*e9be9d5eSMiklos Szeredi char *s = list + off; 263*e9be9d5eSMiklos Szeredi size_t slen = strlen(s) + 1; 264*e9be9d5eSMiklos Szeredi 265*e9be9d5eSMiklos Szeredi BUG_ON(off + slen > res); 266*e9be9d5eSMiklos Szeredi 267*e9be9d5eSMiklos Szeredi if (ovl_is_private_xattr(s)) { 268*e9be9d5eSMiklos Szeredi res -= slen; 269*e9be9d5eSMiklos Szeredi memmove(s, s + slen, res - off); 270*e9be9d5eSMiklos Szeredi } else { 271*e9be9d5eSMiklos Szeredi off += slen; 272*e9be9d5eSMiklos Szeredi } 273*e9be9d5eSMiklos Szeredi } 274*e9be9d5eSMiklos Szeredi 275*e9be9d5eSMiklos Szeredi return res; 276*e9be9d5eSMiklos Szeredi } 277*e9be9d5eSMiklos Szeredi 278*e9be9d5eSMiklos Szeredi int ovl_removexattr(struct dentry *dentry, const char *name) 279*e9be9d5eSMiklos Szeredi { 280*e9be9d5eSMiklos Szeredi int err; 281*e9be9d5eSMiklos Szeredi struct path realpath; 282*e9be9d5eSMiklos Szeredi enum ovl_path_type type; 283*e9be9d5eSMiklos Szeredi 284*e9be9d5eSMiklos Szeredi err = ovl_want_write(dentry); 285*e9be9d5eSMiklos Szeredi if (err) 286*e9be9d5eSMiklos Szeredi goto out; 287*e9be9d5eSMiklos Szeredi 288*e9be9d5eSMiklos Szeredi if (ovl_path_type(dentry->d_parent) == OVL_PATH_MERGE && 289*e9be9d5eSMiklos Szeredi ovl_is_private_xattr(name)) 290*e9be9d5eSMiklos Szeredi goto out_drop_write; 291*e9be9d5eSMiklos Szeredi 292*e9be9d5eSMiklos Szeredi type = ovl_path_real(dentry, &realpath); 293*e9be9d5eSMiklos Szeredi if (type == OVL_PATH_LOWER) { 294*e9be9d5eSMiklos Szeredi err = vfs_getxattr(realpath.dentry, name, NULL, 0); 295*e9be9d5eSMiklos Szeredi if (err < 0) 296*e9be9d5eSMiklos Szeredi goto out_drop_write; 297*e9be9d5eSMiklos Szeredi 298*e9be9d5eSMiklos Szeredi err = ovl_copy_up(dentry); 299*e9be9d5eSMiklos Szeredi if (err) 300*e9be9d5eSMiklos Szeredi goto out_drop_write; 301*e9be9d5eSMiklos Szeredi 302*e9be9d5eSMiklos Szeredi ovl_path_upper(dentry, &realpath); 303*e9be9d5eSMiklos Szeredi } 304*e9be9d5eSMiklos Szeredi 305*e9be9d5eSMiklos Szeredi err = vfs_removexattr(realpath.dentry, name); 306*e9be9d5eSMiklos Szeredi out_drop_write: 307*e9be9d5eSMiklos Szeredi ovl_drop_write(dentry); 308*e9be9d5eSMiklos Szeredi out: 309*e9be9d5eSMiklos Szeredi return err; 310*e9be9d5eSMiklos Szeredi } 311*e9be9d5eSMiklos Szeredi 312*e9be9d5eSMiklos Szeredi static bool ovl_open_need_copy_up(int flags, enum ovl_path_type type, 313*e9be9d5eSMiklos Szeredi struct dentry *realdentry) 314*e9be9d5eSMiklos Szeredi { 315*e9be9d5eSMiklos Szeredi if (type != OVL_PATH_LOWER) 316*e9be9d5eSMiklos Szeredi return false; 317*e9be9d5eSMiklos Szeredi 318*e9be9d5eSMiklos Szeredi if (special_file(realdentry->d_inode->i_mode)) 319*e9be9d5eSMiklos Szeredi return false; 320*e9be9d5eSMiklos Szeredi 321*e9be9d5eSMiklos Szeredi if (!(OPEN_FMODE(flags) & FMODE_WRITE) && !(flags & O_TRUNC)) 322*e9be9d5eSMiklos Szeredi return false; 323*e9be9d5eSMiklos Szeredi 324*e9be9d5eSMiklos Szeredi return true; 325*e9be9d5eSMiklos Szeredi } 326*e9be9d5eSMiklos Szeredi 327*e9be9d5eSMiklos Szeredi static int ovl_dentry_open(struct dentry *dentry, struct file *file, 328*e9be9d5eSMiklos Szeredi const struct cred *cred) 329*e9be9d5eSMiklos Szeredi { 330*e9be9d5eSMiklos Szeredi int err; 331*e9be9d5eSMiklos Szeredi struct path realpath; 332*e9be9d5eSMiklos Szeredi enum ovl_path_type type; 333*e9be9d5eSMiklos Szeredi bool want_write = false; 334*e9be9d5eSMiklos Szeredi 335*e9be9d5eSMiklos Szeredi type = ovl_path_real(dentry, &realpath); 336*e9be9d5eSMiklos Szeredi if (ovl_open_need_copy_up(file->f_flags, type, realpath.dentry)) { 337*e9be9d5eSMiklos Szeredi want_write = true; 338*e9be9d5eSMiklos Szeredi err = ovl_want_write(dentry); 339*e9be9d5eSMiklos Szeredi if (err) 340*e9be9d5eSMiklos Szeredi goto out; 341*e9be9d5eSMiklos Szeredi 342*e9be9d5eSMiklos Szeredi if (file->f_flags & O_TRUNC) 343*e9be9d5eSMiklos Szeredi err = ovl_copy_up_last(dentry, NULL, true); 344*e9be9d5eSMiklos Szeredi else 345*e9be9d5eSMiklos Szeredi err = ovl_copy_up(dentry); 346*e9be9d5eSMiklos Szeredi if (err) 347*e9be9d5eSMiklos Szeredi goto out_drop_write; 348*e9be9d5eSMiklos Szeredi 349*e9be9d5eSMiklos Szeredi ovl_path_upper(dentry, &realpath); 350*e9be9d5eSMiklos Szeredi } 351*e9be9d5eSMiklos Szeredi 352*e9be9d5eSMiklos Szeredi err = vfs_open(&realpath, file, cred); 353*e9be9d5eSMiklos Szeredi out_drop_write: 354*e9be9d5eSMiklos Szeredi if (want_write) 355*e9be9d5eSMiklos Szeredi ovl_drop_write(dentry); 356*e9be9d5eSMiklos Szeredi out: 357*e9be9d5eSMiklos Szeredi return err; 358*e9be9d5eSMiklos Szeredi } 359*e9be9d5eSMiklos Szeredi 360*e9be9d5eSMiklos Szeredi static const struct inode_operations ovl_file_inode_operations = { 361*e9be9d5eSMiklos Szeredi .setattr = ovl_setattr, 362*e9be9d5eSMiklos Szeredi .permission = ovl_permission, 363*e9be9d5eSMiklos Szeredi .getattr = ovl_getattr, 364*e9be9d5eSMiklos Szeredi .setxattr = ovl_setxattr, 365*e9be9d5eSMiklos Szeredi .getxattr = ovl_getxattr, 366*e9be9d5eSMiklos Szeredi .listxattr = ovl_listxattr, 367*e9be9d5eSMiklos Szeredi .removexattr = ovl_removexattr, 368*e9be9d5eSMiklos Szeredi .dentry_open = ovl_dentry_open, 369*e9be9d5eSMiklos Szeredi }; 370*e9be9d5eSMiklos Szeredi 371*e9be9d5eSMiklos Szeredi static const struct inode_operations ovl_symlink_inode_operations = { 372*e9be9d5eSMiklos Szeredi .setattr = ovl_setattr, 373*e9be9d5eSMiklos Szeredi .follow_link = ovl_follow_link, 374*e9be9d5eSMiklos Szeredi .put_link = ovl_put_link, 375*e9be9d5eSMiklos Szeredi .readlink = ovl_readlink, 376*e9be9d5eSMiklos Szeredi .getattr = ovl_getattr, 377*e9be9d5eSMiklos Szeredi .setxattr = ovl_setxattr, 378*e9be9d5eSMiklos Szeredi .getxattr = ovl_getxattr, 379*e9be9d5eSMiklos Szeredi .listxattr = ovl_listxattr, 380*e9be9d5eSMiklos Szeredi .removexattr = ovl_removexattr, 381*e9be9d5eSMiklos Szeredi }; 382*e9be9d5eSMiklos Szeredi 383*e9be9d5eSMiklos Szeredi struct inode *ovl_new_inode(struct super_block *sb, umode_t mode, 384*e9be9d5eSMiklos Szeredi struct ovl_entry *oe) 385*e9be9d5eSMiklos Szeredi { 386*e9be9d5eSMiklos Szeredi struct inode *inode; 387*e9be9d5eSMiklos Szeredi 388*e9be9d5eSMiklos Szeredi inode = new_inode(sb); 389*e9be9d5eSMiklos Szeredi if (!inode) 390*e9be9d5eSMiklos Szeredi return NULL; 391*e9be9d5eSMiklos Szeredi 392*e9be9d5eSMiklos Szeredi mode &= S_IFMT; 393*e9be9d5eSMiklos Szeredi 394*e9be9d5eSMiklos Szeredi inode->i_ino = get_next_ino(); 395*e9be9d5eSMiklos Szeredi inode->i_mode = mode; 396*e9be9d5eSMiklos Szeredi inode->i_flags |= S_NOATIME | S_NOCMTIME; 397*e9be9d5eSMiklos Szeredi 398*e9be9d5eSMiklos Szeredi switch (mode) { 399*e9be9d5eSMiklos Szeredi case S_IFDIR: 400*e9be9d5eSMiklos Szeredi inode->i_private = oe; 401*e9be9d5eSMiklos Szeredi inode->i_op = &ovl_dir_inode_operations; 402*e9be9d5eSMiklos Szeredi inode->i_fop = &ovl_dir_operations; 403*e9be9d5eSMiklos Szeredi break; 404*e9be9d5eSMiklos Szeredi 405*e9be9d5eSMiklos Szeredi case S_IFLNK: 406*e9be9d5eSMiklos Szeredi inode->i_op = &ovl_symlink_inode_operations; 407*e9be9d5eSMiklos Szeredi break; 408*e9be9d5eSMiklos Szeredi 409*e9be9d5eSMiklos Szeredi case S_IFREG: 410*e9be9d5eSMiklos Szeredi case S_IFSOCK: 411*e9be9d5eSMiklos Szeredi case S_IFBLK: 412*e9be9d5eSMiklos Szeredi case S_IFCHR: 413*e9be9d5eSMiklos Szeredi case S_IFIFO: 414*e9be9d5eSMiklos Szeredi inode->i_op = &ovl_file_inode_operations; 415*e9be9d5eSMiklos Szeredi break; 416*e9be9d5eSMiklos Szeredi 417*e9be9d5eSMiklos Szeredi default: 418*e9be9d5eSMiklos Szeredi WARN(1, "illegal file type: %i\n", mode); 419*e9be9d5eSMiklos Szeredi iput(inode); 420*e9be9d5eSMiklos Szeredi inode = NULL; 421*e9be9d5eSMiklos Szeredi } 422*e9be9d5eSMiklos Szeredi 423*e9be9d5eSMiklos Szeredi return inode; 424*e9be9d5eSMiklos Szeredi 425*e9be9d5eSMiklos Szeredi } 426