···18801880 rdev->sysfs_state = sysfs_get_dirent_safe(rdev->kobj.sd, "state");1881188118821882 list_add_rcu(&rdev->same_set, &mddev->disks);18831883- bd_claim_by_disk(rdev->bdev, rdev->bdev->bd_holder, mddev->gendisk);18831883+ bd_link_disk_holder(rdev->bdev, mddev->gendisk);1884188418851885 /* May as well allow recovery to be retried once */18861886 mddev->recovery_disabled = 0;···19071907 MD_BUG();19081908 return;19091909 }19101910- bd_release_from_disk(rdev->bdev, rdev->mddev->gendisk);19111910 list_del_rcu(&rdev->same_set);19121911 printk(KERN_INFO "md: unbind<%s>\n", bdevname(rdev->bdev,b));19131912 rdev->mddev = NULL;···19341935 struct block_device *bdev;19351936 char b[BDEVNAME_SIZE];1936193719371937- bdev = open_by_devnum(dev, FMODE_READ|FMODE_WRITE);19381938+ bdev = blkdev_get_by_dev(dev, FMODE_READ|FMODE_WRITE|FMODE_EXCL,19391939+ shared ? (mdk_rdev_t *)lock_rdev : rdev);19381940 if (IS_ERR(bdev)) {19391941 printk(KERN_ERR "md: could not open %s.\n",19401942 __bdevname(dev, b));19411943 return PTR_ERR(bdev);19421942- }19431943- err = bd_claim(bdev, shared ? (mdk_rdev_t *)lock_rdev : rdev);19441944- if (err) {19451945- printk(KERN_ERR "md: could not bd_claim %s.\n",19461946- bdevname(bdev, b));19471947- blkdev_put(bdev, FMODE_READ|FMODE_WRITE);19481948- return err;19491944 }19501945 if (!shared)19511946 set_bit(AllReserved, &rdev->flags);···19531960 rdev->bdev = NULL;19541961 if (!bdev)19551962 MD_BUG();19561956- bd_release(bdev);19571957- blkdev_put(bdev, FMODE_READ|FMODE_WRITE);19631963+ blkdev_put(bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);19581964}1959196519601966void md_autodetect_dev(dev_t dev);
+5-5
drivers/mtd/devices/block2mtd.c
···224224 if (dev->blkdev) {225225 invalidate_mapping_pages(dev->blkdev->bd_inode->i_mapping,226226 0, -1);227227- close_bdev_exclusive(dev->blkdev, FMODE_READ|FMODE_WRITE);227227+ blkdev_put(dev->blkdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);228228 }229229230230 kfree(dev);···234234/* FIXME: ensure that mtd->size % erase_size == 0 */235235static struct block2mtd_dev *add_device(char *devname, int erase_size)236236{237237+ const fmode_t mode = FMODE_READ | FMODE_WRITE | FMODE_EXCL;237238 struct block_device *bdev;238239 struct block2mtd_dev *dev;239240 char *name;···247246 return NULL;248247249248 /* Get a handle on the device */250250- bdev = open_bdev_exclusive(devname, FMODE_READ|FMODE_WRITE, NULL);249249+ bdev = blkdev_get_by_path(devname, mode, dev);251250#ifndef MODULE252251 if (IS_ERR(bdev)) {253252···255254 to resolve the device name by other means. */256255257256 dev_t devt = name_to_dev_t(devname);258258- if (devt) {259259- bdev = open_by_devnum(devt, FMODE_WRITE | FMODE_READ);260260- }257257+ if (devt)258258+ bdev = blkdev_get_by_dev(devt, mode, dev);261259 }262260#endif263261
+1-1
drivers/s390/block/dasd_genhd.c
···103103 struct block_device *bdev;104104105105 bdev = bdget_disk(block->gdp, 0);106106- if (!bdev || blkdev_get(bdev, FMODE_READ) < 0)106106+ if (!bdev || blkdev_get(bdev, FMODE_READ, NULL) < 0)107107 return -ENODEV;108108 /*109109 * See fs/partition/check.c:register_disk,rescan_partitions
+2-5
drivers/usb/gadget/storage_common.c
···543543 ro = curlun->initially_ro;544544 if (!ro) {545545 filp = filp_open(filename, O_RDWR | O_LARGEFILE, 0);546546- if (-EROFS == PTR_ERR(filp))546546+ if (PTR_ERR(filp) == -EROFS || PTR_ERR(filp) == -EACCES)547547 ro = 1;548548 }549549 if (ro)···558558559559 if (filp->f_path.dentry)560560 inode = filp->f_path.dentry->d_inode;561561- if (inode && S_ISBLK(inode->i_mode)) {562562- if (bdev_read_only(inode->i_bdev))563563- ro = 1;564564- } else if (!inode || !S_ISREG(inode->i_mode)) {561561+ if (!inode || (!S_ISREG(inode->i_mode) && !S_ISBLK(inode->i_mode))) {565562 LINFO(curlun, "invalid file type: %s\n", filename);566563 goto out;567564 }
+227-493
fs/block_dev.c
···426426 mutex_init(&bdev->bd_mutex);427427 INIT_LIST_HEAD(&bdev->bd_inodes);428428 INIT_LIST_HEAD(&bdev->bd_list);429429-#ifdef CONFIG_SYSFS430430- INIT_LIST_HEAD(&bdev->bd_holder_list);431431-#endif432429 inode_init_once(&ei->vfs_inode);433430 /* Initialize mutex for freeze. */434431 mutex_init(&bdev->bd_fsfreeze_mutex);···660663 else if (bdev->bd_contains == bdev)661664 return true; /* is a whole device which isn't held */662665663663- else if (whole->bd_holder == bd_claim)666666+ else if (whole->bd_holder == bd_may_claim)664667 return true; /* is a partition of a device that is being partitioned */665668 else if (whole->bd_holder != NULL)666669 return false; /* is a partition of a held device */···772775 }773776}774777775775-/* releases bdev_lock */776776-static void __bd_abort_claiming(struct block_device *whole, void *holder)777777-{778778- BUG_ON(whole->bd_claiming != holder);779779- whole->bd_claiming = NULL;780780- wake_up_bit(&whole->bd_claiming, 0);781781-782782- spin_unlock(&bdev_lock);783783- bdput(whole);784784-}785785-786786-/**787787- * bd_abort_claiming - abort claiming a block device788788- * @whole: whole block device returned by bd_start_claiming()789789- * @holder: holder trying to claim @bdev790790- *791791- * Abort a claiming block started by bd_start_claiming(). Note that792792- * @whole is not the block device to be claimed but the whole device793793- * returned by bd_start_claiming().794794- *795795- * CONTEXT:796796- * Grabs and releases bdev_lock.797797- */798798-static void bd_abort_claiming(struct block_device *whole, void *holder)799799-{800800- spin_lock(&bdev_lock);801801- __bd_abort_claiming(whole, holder); /* releases bdev_lock */802802-}803803-804804-/* increment holders when we have a legitimate claim. requires bdev_lock */805805-static void __bd_claim(struct block_device *bdev, struct block_device *whole,806806- void *holder)807807-{808808- /* note that for a whole device bd_holders809809- * will be incremented twice, and bd_holder will810810- * be set to bd_claim before being set to holder811811- */812812- whole->bd_holders++;813813- whole->bd_holder = bd_claim;814814- bdev->bd_holders++;815815- bdev->bd_holder = holder;816816-}817817-818818-/**819819- * bd_finish_claiming - finish claiming a block device820820- * @bdev: block device of interest (passed to bd_start_claiming())821821- * @whole: whole block device returned by bd_start_claiming()822822- * @holder: holder trying to claim @bdev823823- *824824- * Finish a claiming block started by bd_start_claiming().825825- *826826- * CONTEXT:827827- * Grabs and releases bdev_lock.828828- */829829-static void bd_finish_claiming(struct block_device *bdev,830830- struct block_device *whole, void *holder)831831-{832832- spin_lock(&bdev_lock);833833- BUG_ON(!bd_may_claim(bdev, whole, holder));834834- __bd_claim(bdev, whole, holder);835835- __bd_abort_claiming(whole, holder); /* not actually an abort */836836-}837837-838838-/**839839- * bd_claim - claim a block device840840- * @bdev: block device to claim841841- * @holder: holder trying to claim @bdev842842- *843843- * Try to claim @bdev which must have been opened successfully.844844- *845845- * CONTEXT:846846- * Might sleep.847847- *848848- * RETURNS:849849- * 0 if successful, -EBUSY if @bdev is already claimed.850850- */851851-int bd_claim(struct block_device *bdev, void *holder)852852-{853853- struct block_device *whole = bdev->bd_contains;854854- int res;855855-856856- might_sleep();857857-858858- spin_lock(&bdev_lock);859859- res = bd_prepare_to_claim(bdev, whole, holder);860860- if (res == 0)861861- __bd_claim(bdev, whole, holder);862862- spin_unlock(&bdev_lock);863863-864864- return res;865865-}866866-EXPORT_SYMBOL(bd_claim);867867-868868-void bd_release(struct block_device *bdev)869869-{870870- spin_lock(&bdev_lock);871871- if (!--bdev->bd_contains->bd_holders)872872- bdev->bd_contains->bd_holder = NULL;873873- if (!--bdev->bd_holders)874874- bdev->bd_holder = NULL;875875- spin_unlock(&bdev_lock);876876-}877877-878878-EXPORT_SYMBOL(bd_release);879879-880778#ifdef CONFIG_SYSFS881881-/*882882- * Functions for bd_claim_by_kobject / bd_release_from_kobject883883- *884884- * If a kobject is passed to bd_claim_by_kobject()885885- * and the kobject has a parent directory,886886- * following symlinks are created:887887- * o from the kobject to the claimed bdev888888- * o from "holders" directory of the bdev to the parent of the kobject889889- * bd_release_from_kobject() removes these symlinks.890890- *891891- * Example:892892- * If /dev/dm-0 maps to /dev/sda, kobject corresponding to893893- * /sys/block/dm-0/slaves is passed to bd_claim_by_kobject(), then:894894- * /sys/block/dm-0/slaves/sda --> /sys/block/sda895895- * /sys/block/sda/holders/dm-0 --> /sys/block/dm-0896896- */897897-898779static int add_symlink(struct kobject *from, struct kobject *to)899780{900900- if (!from || !to)901901- return 0;902781 return sysfs_create_link(from, to, kobject_name(to));903782}904783905784static void del_symlink(struct kobject *from, struct kobject *to)906785{907907- if (!from || !to)908908- return;909786 sysfs_remove_link(from, kobject_name(to));910787}911788912912-/*913913- * 'struct bd_holder' contains pointers to kobjects symlinked by914914- * bd_claim_by_kobject.915915- * It's connected to bd_holder_list which is protected by bdev->bd_sem.916916- */917917-struct bd_holder {918918- struct list_head list; /* chain of holders of the bdev */919919- int count; /* references from the holder */920920- struct kobject *sdir; /* holder object, e.g. "/block/dm-0/slaves" */921921- struct kobject *hdev; /* e.g. "/block/dm-0" */922922- struct kobject *hdir; /* e.g. "/block/sda/holders" */923923- struct kobject *sdev; /* e.g. "/block/sda" */924924-};925925-926926-/*927927- * Get references of related kobjects at once.928928- * Returns 1 on success. 0 on failure.929929- *930930- * Should call bd_holder_release_dirs() after successful use.931931- */932932-static int bd_holder_grab_dirs(struct block_device *bdev,933933- struct bd_holder *bo)934934-{935935- if (!bdev || !bo)936936- return 0;937937-938938- bo->sdir = kobject_get(bo->sdir);939939- if (!bo->sdir)940940- return 0;941941-942942- bo->hdev = kobject_get(bo->sdir->parent);943943- if (!bo->hdev)944944- goto fail_put_sdir;945945-946946- bo->sdev = kobject_get(&part_to_dev(bdev->bd_part)->kobj);947947- if (!bo->sdev)948948- goto fail_put_hdev;949949-950950- bo->hdir = kobject_get(bdev->bd_part->holder_dir);951951- if (!bo->hdir)952952- goto fail_put_sdev;953953-954954- return 1;955955-956956-fail_put_sdev:957957- kobject_put(bo->sdev);958958-fail_put_hdev:959959- kobject_put(bo->hdev);960960-fail_put_sdir:961961- kobject_put(bo->sdir);962962-963963- return 0;964964-}965965-966966-/* Put references of related kobjects at once. */967967-static void bd_holder_release_dirs(struct bd_holder *bo)968968-{969969- kobject_put(bo->hdir);970970- kobject_put(bo->sdev);971971- kobject_put(bo->hdev);972972- kobject_put(bo->sdir);973973-}974974-975975-static struct bd_holder *alloc_bd_holder(struct kobject *kobj)976976-{977977- struct bd_holder *bo;978978-979979- bo = kzalloc(sizeof(*bo), GFP_KERNEL);980980- if (!bo)981981- return NULL;982982-983983- bo->count = 1;984984- bo->sdir = kobj;985985-986986- return bo;987987-}988988-989989-static void free_bd_holder(struct bd_holder *bo)990990-{991991- kfree(bo);992992-}993993-994789/**995995- * find_bd_holder - find matching struct bd_holder from the block device790790+ * bd_link_disk_holder - create symlinks between holding disk and slave bdev791791+ * @bdev: the claimed slave bdev792792+ * @disk: the holding disk996793 *997997- * @bdev: struct block device to be searched998998- * @bo: target struct bd_holder794794+ * This functions creates the following sysfs symlinks.999795 *10001000- * Returns matching entry with @bo in @bdev->bd_holder_list.10011001- * If found, increment the reference count and return the pointer.10021002- * If not found, returns NULL.796796+ * - from "slaves" directory of the holder @disk to the claimed @bdev797797+ * - from "holders" directory of the @bdev to the holder @disk798798+ *799799+ * For example, if /dev/dm-0 maps to /dev/sda and disk for dm-0 is800800+ * passed to bd_link_disk_holder(), then:801801+ *802802+ * /sys/block/dm-0/slaves/sda --> /sys/block/sda803803+ * /sys/block/sda/holders/dm-0 --> /sys/block/dm-0804804+ *805805+ * The caller must have claimed @bdev before calling this function and806806+ * ensure that both @bdev and @disk are valid during the creation and807807+ * lifetime of these symlinks.808808+ *809809+ * CONTEXT:810810+ * Might sleep.811811+ *812812+ * RETURNS:813813+ * 0 on success, -errno on failure.1003814 */10041004-static struct bd_holder *find_bd_holder(struct block_device *bdev,10051005- struct bd_holder *bo)815815+int bd_link_disk_holder(struct block_device *bdev, struct gendisk *disk)1006816{10071007- struct bd_holder *tmp;10081008-10091009- list_for_each_entry(tmp, &bdev->bd_holder_list, list)10101010- if (tmp->sdir == bo->sdir) {10111011- tmp->count++;10121012- return tmp;10131013- }10141014-10151015- return NULL;10161016-}10171017-10181018-/**10191019- * add_bd_holder - create sysfs symlinks for bd_claim() relationship10201020- *10211021- * @bdev: block device to be bd_claimed10221022- * @bo: preallocated and initialized by alloc_bd_holder()10231023- *10241024- * Add @bo to @bdev->bd_holder_list, create symlinks.10251025- *10261026- * Returns 0 if symlinks are created.10271027- * Returns -ve if something fails.10281028- */10291029-static int add_bd_holder(struct block_device *bdev, struct bd_holder *bo)10301030-{10311031- int err;10321032-10331033- if (!bo)10341034- return -EINVAL;10351035-10361036- if (!bd_holder_grab_dirs(bdev, bo))10371037- return -EBUSY;10381038-10391039- err = add_symlink(bo->sdir, bo->sdev);10401040- if (err)10411041- return err;10421042-10431043- err = add_symlink(bo->hdir, bo->hdev);10441044- if (err) {10451045- del_symlink(bo->sdir, bo->sdev);10461046- return err;10471047- }10481048-10491049- list_add_tail(&bo->list, &bdev->bd_holder_list);10501050- return 0;10511051-}10521052-10531053-/**10541054- * del_bd_holder - delete sysfs symlinks for bd_claim() relationship10551055- *10561056- * @bdev: block device to be bd_claimed10571057- * @kobj: holder's kobject10581058- *10591059- * If there is matching entry with @kobj in @bdev->bd_holder_list10601060- * and no other bd_claim() from the same kobject,10611061- * remove the struct bd_holder from the list, delete symlinks for it.10621062- *10631063- * Returns a pointer to the struct bd_holder when it's removed from the list10641064- * and ready to be freed.10651065- * Returns NULL if matching claim isn't found or there is other bd_claim()10661066- * by the same kobject.10671067- */10681068-static struct bd_holder *del_bd_holder(struct block_device *bdev,10691069- struct kobject *kobj)10701070-{10711071- struct bd_holder *bo;10721072-10731073- list_for_each_entry(bo, &bdev->bd_holder_list, list) {10741074- if (bo->sdir == kobj) {10751075- bo->count--;10761076- BUG_ON(bo->count < 0);10771077- if (!bo->count) {10781078- list_del(&bo->list);10791079- del_symlink(bo->sdir, bo->sdev);10801080- del_symlink(bo->hdir, bo->hdev);10811081- bd_holder_release_dirs(bo);10821082- return bo;10831083- }10841084- break;10851085- }10861086- }10871087-10881088- return NULL;10891089-}10901090-10911091-/**10921092- * bd_claim_by_kobject - bd_claim() with additional kobject signature10931093- *10941094- * @bdev: block device to be claimed10951095- * @holder: holder's signature10961096- * @kobj: holder's kobject10971097- *10981098- * Do bd_claim() and if it succeeds, create sysfs symlinks between10991099- * the bdev and the holder's kobject.11001100- * Use bd_release_from_kobject() when relesing the claimed bdev.11011101- *11021102- * Returns 0 on success. (same as bd_claim())11031103- * Returns errno on failure.11041104- */11051105-static int bd_claim_by_kobject(struct block_device *bdev, void *holder,11061106- struct kobject *kobj)11071107-{11081108- int err;11091109- struct bd_holder *bo, *found;11101110-11111111- if (!kobj)11121112- return -EINVAL;11131113-11141114- bo = alloc_bd_holder(kobj);11151115- if (!bo)11161116- return -ENOMEM;817817+ int ret = 0;11178181118819 mutex_lock(&bdev->bd_mutex);111982011201120- err = bd_claim(bdev, holder);11211121- if (err)11221122- goto fail;821821+ WARN_ON_ONCE(!bdev->bd_holder || bdev->bd_holder_disk);112382211241124- found = find_bd_holder(bdev, bo);11251125- if (found)11261126- goto fail;823823+ /* FIXME: remove the following once add_disk() handles errors */824824+ if (WARN_ON(!disk->slave_dir || !bdev->bd_part->holder_dir))825825+ goto out_unlock;112782611281128- err = add_bd_holder(bdev, bo);11291129- if (err)11301130- bd_release(bdev);11311131- else11321132- bo = NULL;11331133-fail:827827+ ret = add_symlink(disk->slave_dir, &part_to_dev(bdev->bd_part)->kobj);828828+ if (ret)829829+ goto out_unlock;830830+831831+ ret = add_symlink(bdev->bd_part->holder_dir, &disk_to_dev(disk)->kobj);832832+ if (ret) {833833+ del_symlink(disk->slave_dir, &part_to_dev(bdev->bd_part)->kobj);834834+ goto out_unlock;835835+ }836836+837837+ bdev->bd_holder_disk = disk;838838+out_unlock:1134839 mutex_unlock(&bdev->bd_mutex);11351135- free_bd_holder(bo);11361136- return err;840840+ return ret;1137841}842842+EXPORT_SYMBOL_GPL(bd_link_disk_holder);113884311391139-/**11401140- * bd_release_from_kobject - bd_release() with additional kobject signature11411141- *11421142- * @bdev: block device to be released11431143- * @kobj: holder's kobject11441144- *11451145- * Do bd_release() and remove sysfs symlinks created by bd_claim_by_kobject().11461146- */11471147-static void bd_release_from_kobject(struct block_device *bdev,11481148- struct kobject *kobj)844844+static void bd_unlink_disk_holder(struct block_device *bdev)1149845{11501150- if (!kobj)846846+ struct gendisk *disk = bdev->bd_holder_disk;847847+848848+ bdev->bd_holder_disk = NULL;849849+ if (!disk)1151850 return;115285111531153- mutex_lock(&bdev->bd_mutex);11541154- bd_release(bdev);11551155- free_bd_holder(del_bd_holder(bdev, kobj));11561156- mutex_unlock(&bdev->bd_mutex);852852+ del_symlink(disk->slave_dir, &part_to_dev(bdev->bd_part)->kobj);853853+ del_symlink(bdev->bd_part->holder_dir, &disk_to_dev(disk)->kobj);1157854}11581158-11591159-/**11601160- * bd_claim_by_disk - wrapper function for bd_claim_by_kobject()11611161- *11621162- * @bdev: block device to be claimed11631163- * @holder: holder's signature11641164- * @disk: holder's gendisk11651165- *11661166- * Call bd_claim_by_kobject() with getting @disk->slave_dir.11671167- */11681168-int bd_claim_by_disk(struct block_device *bdev, void *holder,11691169- struct gendisk *disk)11701170-{11711171- return bd_claim_by_kobject(bdev, holder, kobject_get(disk->slave_dir));11721172-}11731173-EXPORT_SYMBOL_GPL(bd_claim_by_disk);11741174-11751175-/**11761176- * bd_release_from_disk - wrapper function for bd_release_from_kobject()11771177- *11781178- * @bdev: block device to be claimed11791179- * @disk: holder's gendisk11801180- *11811181- * Call bd_release_from_kobject() and put @disk->slave_dir.11821182- */11831183-void bd_release_from_disk(struct block_device *bdev, struct gendisk *disk)11841184-{11851185- bd_release_from_kobject(bdev, disk->slave_dir);11861186- kobject_put(disk->slave_dir);11871187-}11881188-EXPORT_SYMBOL_GPL(bd_release_from_disk);855855+#else856856+static inline void bd_unlink_disk_holder(struct block_device *bdev)857857+{ }1189858#endif11901190-11911191-/*11921192- * Tries to open block device by device number. Use it ONLY if you11931193- * really do not have anything better - i.e. when you are behind a11941194- * truly sucky interface and all you are given is a device number. _Never_11951195- * to be used for internal purposes. If you ever need it - reconsider11961196- * your API.11971197- */11981198-struct block_device *open_by_devnum(dev_t dev, fmode_t mode)11991199-{12001200- struct block_device *bdev = bdget(dev);12011201- int err = -ENOMEM;12021202- if (bdev)12031203- err = blkdev_get(bdev, mode);12041204- return err ? ERR_PTR(err) : bdev;12051205-}12061206-12071207-EXPORT_SYMBOL(open_by_devnum);12088591209860/**1210861 * flush_disk - invalidates all buffer-cache entries on a disk···11141469 return ret;11151470}1116147111171117-int blkdev_get(struct block_device *bdev, fmode_t mode)14721472+/**14731473+ * blkdev_get - open a block device14741474+ * @bdev: block_device to open14751475+ * @mode: FMODE_* mask14761476+ * @holder: exclusive holder identifier14771477+ *14781478+ * Open @bdev with @mode. If @mode includes %FMODE_EXCL, @bdev is14791479+ * open with exclusive access. Specifying %FMODE_EXCL with %NULL14801480+ * @holder is invalid. Exclusive opens may nest for the same @holder.14811481+ *14821482+ * On success, the reference count of @bdev is unchanged. On failure,14831483+ * @bdev is put.14841484+ *14851485+ * CONTEXT:14861486+ * Might sleep.14871487+ *14881488+ * RETURNS:14891489+ * 0 on success, -errno on failure.14901490+ */14911491+int blkdev_get(struct block_device *bdev, fmode_t mode, void *holder)11181492{11191119- return __blkdev_get(bdev, mode, 0);14931493+ struct block_device *whole = NULL;14941494+ int res;14951495+14961496+ WARN_ON_ONCE((mode & FMODE_EXCL) && !holder);14971497+14981498+ if ((mode & FMODE_EXCL) && holder) {14991499+ whole = bd_start_claiming(bdev, holder);15001500+ if (IS_ERR(whole)) {15011501+ bdput(bdev);15021502+ return PTR_ERR(whole);15031503+ }15041504+ }15051505+15061506+ res = __blkdev_get(bdev, mode, 0);15071507+15081508+ /* __blkdev_get() may alter read only status, check it afterwards */15091509+ if (!res && (mode & FMODE_WRITE) && bdev_read_only(bdev)) {15101510+ __blkdev_put(bdev, mode, 0);15111511+ res = -EACCES;15121512+ }15131513+15141514+ if (whole) {15151515+ /* finish claiming */15161516+ spin_lock(&bdev_lock);15171517+15181518+ if (res == 0) {15191519+ BUG_ON(!bd_may_claim(bdev, whole, holder));15201520+ /*15211521+ * Note that for a whole device bd_holders15221522+ * will be incremented twice, and bd_holder15231523+ * will be set to bd_may_claim before being15241524+ * set to holder15251525+ */15261526+ whole->bd_holders++;15271527+ whole->bd_holder = bd_may_claim;15281528+ bdev->bd_holders++;15291529+ bdev->bd_holder = holder;15301530+ }15311531+15321532+ /* tell others that we're done */15331533+ BUG_ON(whole->bd_claiming != holder);15341534+ whole->bd_claiming = NULL;15351535+ wake_up_bit(&whole->bd_claiming, 0);15361536+15371537+ spin_unlock(&bdev_lock);15381538+ bdput(whole);15391539+ }15401540+15411541+ return res;11201542}11211543EXPORT_SYMBOL(blkdev_get);1122154415451545+/**15461546+ * blkdev_get_by_path - open a block device by name15471547+ * @path: path to the block device to open15481548+ * @mode: FMODE_* mask15491549+ * @holder: exclusive holder identifier15501550+ *15511551+ * Open the blockdevice described by the device file at @path. @mode15521552+ * and @holder are identical to blkdev_get().15531553+ *15541554+ * On success, the returned block_device has reference count of one.15551555+ *15561556+ * CONTEXT:15571557+ * Might sleep.15581558+ *15591559+ * RETURNS:15601560+ * Pointer to block_device on success, ERR_PTR(-errno) on failure.15611561+ */15621562+struct block_device *blkdev_get_by_path(const char *path, fmode_t mode,15631563+ void *holder)15641564+{15651565+ struct block_device *bdev;15661566+ int err;15671567+15681568+ bdev = lookup_bdev(path);15691569+ if (IS_ERR(bdev))15701570+ return bdev;15711571+15721572+ err = blkdev_get(bdev, mode, holder);15731573+ if (err)15741574+ return ERR_PTR(err);15751575+15761576+ return bdev;15771577+}15781578+EXPORT_SYMBOL(blkdev_get_by_path);15791579+15801580+/**15811581+ * blkdev_get_by_dev - open a block device by device number15821582+ * @dev: device number of block device to open15831583+ * @mode: FMODE_* mask15841584+ * @holder: exclusive holder identifier15851585+ *15861586+ * Open the blockdevice described by device number @dev. @mode and15871587+ * @holder are identical to blkdev_get().15881588+ *15891589+ * Use it ONLY if you really do not have anything better - i.e. when15901590+ * you are behind a truly sucky interface and all you are given is a15911591+ * device number. _Never_ to be used for internal purposes. If you15921592+ * ever need it - reconsider your API.15931593+ *15941594+ * On success, the returned block_device has reference count of one.15951595+ *15961596+ * CONTEXT:15971597+ * Might sleep.15981598+ *15991599+ * RETURNS:16001600+ * Pointer to block_device on success, ERR_PTR(-errno) on failure.16011601+ */16021602+struct block_device *blkdev_get_by_dev(dev_t dev, fmode_t mode, void *holder)16031603+{16041604+ struct block_device *bdev;16051605+ int err;16061606+16071607+ bdev = bdget(dev);16081608+ if (!bdev)16091609+ return ERR_PTR(-ENOMEM);16101610+16111611+ err = blkdev_get(bdev, mode, holder);16121612+ if (err)16131613+ return ERR_PTR(err);16141614+16151615+ return bdev;16161616+}16171617+EXPORT_SYMBOL(blkdev_get_by_dev);16181618+11231619static int blkdev_open(struct inode * inode, struct file * filp)11241620{11251125- struct block_device *whole = NULL;11261621 struct block_device *bdev;11271127- int res;1128162211291623 /*11301624 * Preserve backwards compatibility and allow large file access···12841500 if (bdev == NULL)12851501 return -ENOMEM;1286150212871287- if (filp->f_mode & FMODE_EXCL) {12881288- whole = bd_start_claiming(bdev, filp);12891289- if (IS_ERR(whole)) {12901290- bdput(bdev);12911291- return PTR_ERR(whole);12921292- }12931293- }12941294-12951503 filp->f_mapping = bdev->bd_inode->i_mapping;1296150412971297- res = blkdev_get(bdev, filp->f_mode);12981298-12991299- if (whole) {13001300- if (res == 0)13011301- bd_finish_claiming(bdev, whole, filp);13021302- else13031303- bd_abort_claiming(whole, filp);13041304- }13051305-13061306- return res;15051505+ return blkdev_get(bdev, filp->f_mode, filp);13071506}1308150713091508static int __blkdev_put(struct block_device *bdev, fmode_t mode, int for_part)···13001533 bdev->bd_part_count--;1301153413021535 if (!--bdev->bd_openers) {15361536+ WARN_ON_ONCE(bdev->bd_holders);13031537 sync_blockdev(bdev);13041538 kill_bdev(bdev);13051539 }···1331156313321564int blkdev_put(struct block_device *bdev, fmode_t mode)13331565{15661566+ if (mode & FMODE_EXCL) {15671567+ bool bdev_free;15681568+15691569+ /*15701570+ * Release a claim on the device. The holder fields15711571+ * are protected with bdev_lock. bd_mutex is to15721572+ * synchronize disk_holder unlinking.15731573+ */15741574+ mutex_lock(&bdev->bd_mutex);15751575+ spin_lock(&bdev_lock);15761576+15771577+ WARN_ON_ONCE(--bdev->bd_holders < 0);15781578+ WARN_ON_ONCE(--bdev->bd_contains->bd_holders < 0);15791579+15801580+ /* bd_contains might point to self, check in a separate step */15811581+ if ((bdev_free = !bdev->bd_holders))15821582+ bdev->bd_holder = NULL;15831583+ if (!bdev->bd_contains->bd_holders)15841584+ bdev->bd_contains->bd_holder = NULL;15851585+15861586+ spin_unlock(&bdev_lock);15871587+15881588+ /* if this was the last claim, holder link should go too */15891589+ if (bdev_free)15901590+ bd_unlink_disk_holder(bdev);15911591+15921592+ mutex_unlock(&bdev->bd_mutex);15931593+ }13341594 return __blkdev_put(bdev, mode, 0);13351595}13361596EXPORT_SYMBOL(blkdev_put);···13661570static int blkdev_close(struct inode * inode, struct file * filp)13671571{13681572 struct block_device *bdev = I_BDEV(filp->f_mapping->host);13691369- if (bdev->bd_holder == filp)13701370- bd_release(bdev);15731573+13711574 return blkdev_put(bdev, filp->f_mode);13721575}13731576···15101715 goto out;15111716}15121717EXPORT_SYMBOL(lookup_bdev);15131513-15141514-/**15151515- * open_bdev_exclusive - open a block device by name and set it up for use15161516- *15171517- * @path: special file representing the block device15181518- * @mode: FMODE_... combination to pass be used15191519- * @holder: owner for exclusion15201520- *15211521- * Open the blockdevice described by the special file at @path, claim it15221522- * for the @holder.15231523- */15241524-struct block_device *open_bdev_exclusive(const char *path, fmode_t mode, void *holder)15251525-{15261526- struct block_device *bdev, *whole;15271527- int error;15281528-15291529- bdev = lookup_bdev(path);15301530- if (IS_ERR(bdev))15311531- return bdev;15321532-15331533- whole = bd_start_claiming(bdev, holder);15341534- if (IS_ERR(whole)) {15351535- bdput(bdev);15361536- return whole;15371537- }15381538-15391539- error = blkdev_get(bdev, mode);15401540- if (error)15411541- goto out_abort_claiming;15421542-15431543- error = -EACCES;15441544- if ((mode & FMODE_WRITE) && bdev_read_only(bdev))15451545- goto out_blkdev_put;15461546-15471547- bd_finish_claiming(bdev, whole, holder);15481548- return bdev;15491549-15501550-out_blkdev_put:15511551- blkdev_put(bdev, mode);15521552-out_abort_claiming:15531553- bd_abort_claiming(whole, holder);15541554- return ERR_PTR(error);15551555-}15561556-15571557-EXPORT_SYMBOL(open_bdev_exclusive);15581558-15591559-/**15601560- * close_bdev_exclusive - close a blockdevice opened by open_bdev_exclusive()15611561- *15621562- * @bdev: blockdevice to close15631563- * @mode: mode, must match that used to open.15641564- *15651565- * This is the counterpart to open_bdev_exclusive().15661566- */15671567-void close_bdev_exclusive(struct block_device *bdev, fmode_t mode)15681568-{15691569- bd_release(bdev);15701570- blkdev_put(bdev, mode);15711571-}15721572-15731573-EXPORT_SYMBOL(close_bdev_exclusive);1574171815751719int __invalidate_device(struct block_device *bdev)15761720{
···49495050 struct block_device *bdev;51515252- /* the mode sent to open_bdev_exclusive */5252+ /* the mode sent to blkdev_get */5353 fmode_t mode;54545555 char *name;